🚀 ShardingSphere 🚀 |
🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀
🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨
🌲 作者简介:硕风和炜,CSDN-Java领域优质创作者🏆,保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文|经验分享|好用的网站工具分享💎💎💎
🌲 恭喜你发现一枚宝藏博主,赶快收入囊中吧🌻
🌲 人生如棋,我愿为卒,行动虽慢,可谁曾见我后退一步?🎯🎯
🚀 ShardingSphere 🚀 |
🍔 目录
- 🍀 一.Sharding-JDBC强制路由基本概念
- 🍀 二.Sharding-JDBC强制路由案例实战
- 🥦 2.1 数据环境准备
- 🥦 2.2 创建SpringBoot程序 - 导入依赖
- 🥦 2.3 创建SpringBoot程序 - 实体类
- 🥦 2.4 创建SpringBoot程序 - 数据库Mapper接口 & 主启动类
- 🥦 2.5 创建SpringBoot程序 - 自定义强制路由配置类
- 🥦 2.6 创建SpringBoot程序 - 强制路由配置文件
- 🍀 三.Sharding-JDBC强制路由案例测试
- 🥦 3.1 强制路由到库测试
- 🥦 3.2 强制路由到库到表测试
- 🍀 四.总结
- 💬 五.共勉
🍀 一.Sharding-JDBC强制路由基本概念
在一些应用场景中,分片条件依赖于外部业务逻辑。因此需要提供一种通过在外部业务代码中指定路由配置的一种方式,在ShardingSphere中叫做Hint。如果使用Hint指定了强制分片路由,那么SQL将会无视原有的分片逻辑,直接路由至指定的数据节点操作。ShardingSphere使用ThreadLocal管理分片键值进行Hint强制路由。可以通过编程的方式向HintManager中添加分片值,该分片值仅在当前线程内生效。
Hint使用场景:
- 数据分片操作,如果分片键没有在SQL或数据表中,而是在业务逻辑代码中
- 读写分离操作,如果强制在主库进行某些数据操作
Sharding-JDBC强制路由案例实战官方指导手册
🍀 二.Sharding-JDBC强制路由案例实战
🥦 2.1 数据环境准备
没有创建过的同学们需要在 ljw_course_db1
和 ljw_course_db2
中创建 t_course表.
CREATE TABLE `t_course` (
`cid` bigint(20) NOT NULL,
`user_id` bigint(20) DEFAULT NULL,
`corder_no` bigint(20) DEFAULT NULL,
`cname` varchar(50) DEFAULT NULL,
`brief` varchar(50) DEFAULT NULL,
`price` double DEFAULT NULL,
`status` int(11) DEFAULT NULL,
PRIMARY KEY (`cid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
🥦 2.2 创建SpringBoot程序 - 导入依赖
引入依赖 (注意: 在这里使用ShardingSphere4.1版本为案例
进行强制路由的实战)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>shardingjdbc-hint</artifactId>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-core-common</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.8</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
🥦 2.3 创建SpringBoot程序 - 实体类
与数据库表中对应的实体类
@TableName("t_course")
@Data
@ToString
public class Course {
@TableId(type = IdType.ASSIGN_ID)
private Long cid;
private Long userId;
private Long corderNo;
private String cname;
private String brief;
private double price;
private int status;
}
🥦 2.4 创建SpringBoot程序 - 数据库Mapper接口 & 主启动类
编写对应的数据库持久层CourseMapper接口
@Repository
public interface CourseMapper extends BaseMapper<Course> {
}
@Repository注解的类需要交给我们的Spring容器进行管理,因此需要我们在主启动类加上扫描接口的注解。
@SpringBootApplication
@MapperScan("com.ljw.mapper")
public class ShardingSphereApplication {
public static void main(String[] args) {
SpringApplication.run(ShardingSphereApplication.class,args);
}
}
🥦 2.5 创建SpringBoot程序 - 自定义强制路由配置类
在自定义类中编写分库或分表路由策略,实现HintShardingAlgorithm接口,并且重写doSharding方法
public class HintShardingAlgorithmConfig implements HintShardingAlgorithm<Long> {
/**
* 定义强制路由策略
* collection: 代表分片目标: 对哪些数据库 表进行分片,比如做分库路由,集合中就存储着 db1.t_course, db1.t_course
* hintShardingValue: 代表分片值, 指的是使用者对分片键赋的值
*/
@Override
public Collection<String> doSharding(Collection<String> collection, HintShardingValue<Long> hintShardingValue) {
// 结果收集
Collection<String> result = new ArrayList<>();
// 遍历数据库
// collection: 代表分片目标: 对哪些数据库 表进行分片,比如做分库路由,集合中就存储着 db1.t_course, db1.t_course
for (String actualDb : collection) {
// hintShardingValue: 代表分片值, 指的是使用者对分片键赋的值
Collection<Long> values = hintShardingValue.getValues();
for (Long value : values) {
//分库路由 判断当前节点名称结尾 是否与取模结果一致
if(actualDb.endsWith(String.valueOf(value % 2 + 1))){
result.add(actualDb);
}
}
}
return result;
}
}
🥦 2.6 创建SpringBoot程序 - 强制路由配置文件
配置读写分离相关配置的信息
# 应用名称
spring.application.name=sharding-jdbc-hint
# 打印SQl
spring.shardingsphere.props.sql-show=true
# 定义多个数据源
spring.shardingsphere.datasource.names = db1,db2
# 数据源1
spring.shardingsphere.datasource.db1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.db1.jdbc-url=jdbc:mysql://192.168.10.132:3306/ljw_course_db1?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=root
# 数据源2
spring.shardingsphere.datasource.db2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.db2.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.db2.jdbc-url=jdbc:mysql://192.168.10.133:3306/ljw_course_db2?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.shardingsphere.datasource.db2.username=root
spring.shardingsphere.datasource.db2.password=root
# 配置默认数据源db1
spring.shardingsphere.sharding.default-data-source-name=db1
# Hint强制路由
# 使用t_course表测试强制路由到库
spring.shardingsphere.sharding.tables.t_course.database-strategy.hint.algorithm-class-name=com.ljw.hint.HintShardingAlgorithmConfig
# 强制路由到指定表
spring.shardingsphere.sharding.tables.t_course.table-strategy.hint.algorithm-class-name=com.ljw.hint.HintShardingAlgorithmConfig
#配置数据节点 指定t_course逻辑表表的真实分布情况
spring.shardingsphere.sharding.tables.t_course.actual-data-nodes=db$->{1..2}.t_course_$->{1..2}
🍀 三.Sharding-JDBC强制路由案例测试
先将我们数据库中表中原来的数据都删除掉,如果是新建的同学就不用了!
🥦 3.1 强制路由到库测试
@Autowired
private CourseMapper courseMapper;
//测试强制路由 到指定库的插入操作
@Test
public void testInsertCourse(){
//通过hintManager指定执行策略的分片键的值
HintManager hintManager = HintManager.getInstance();
//强制路由到db2,此时我们需要传入1,因为我们配置类的逻辑是vlaue%2+1->1%2+1
hintManager.setDatabaseShardingValue(1L);
for (int i = 0; i < 6; i++) {
Course course = new Course();
course.setUserId(1000L+i);
course.setCname("Sharding-JDBC强制路由案例实战");
course.setBrief("全网Sharding-JDBC强制路由案例实战最详细讲解!!!");
course.setPrice(8939.00);
course.setStatus(0);
courseMapper.insert(course);
}
}
运行结果:
🥦 3.2 强制路由到库到表测试
@Autowired
private CourseMapper courseMapper;
@Test
public void testHintDbToTable(){
HintManager hintManager = HintManager.getInstance();
//强制路由到指定库 -> db2
hintManager.addDatabaseShardingValue("t_course",1L);
//强制路由到指定表 ->course1
hintManager.addTableShardingValue("t_course",0L);
List<Course> courses = courseMapper.selectList(null);
courses.forEach(System.out::println);
}
运行结果:
🍀 四.总结
本篇文章主要讲解了Sharding-JDBC强制路由案例实战,实操过程非常重要,大家一定要动手亲自实践一下,必须掌握。下节预告,数据加密详解与实战,大家敬请期待呦!!!。
💬 五.共勉
最后,我想和大家分享一句一直激励我的座右铭,希望可以与大家共勉! |