淺談Sharding-JDBC強(qiáng)制路由案例實(shí)戰(zhàn)
?? 一.Sharding-JDBC強(qiáng)制路由基本概念
在一些應(yīng)用場(chǎng)景中,分片條件依賴于外部業(yè)務(wù)邏輯。因此需要提供一種通過(guò)在外部業(yè)務(wù)代碼中指定路由配置的一種方式,在ShardingSphere中叫做Hint。如果使用Hint指定了強(qiáng)制分片路由,那么SQL將會(huì)無(wú)視原有的分片邏輯,直接路由至指定的數(shù)據(jù)節(jié)點(diǎn)操作。ShardingSphere使用ThreadLocal管理分片鍵值進(jìn)行Hint強(qiáng)制路由??梢酝ㄟ^(guò)編程的方式向HintManager中添加分片值,該分片值僅在當(dāng)前線程內(nèi)生效。
Hint使用場(chǎng)景:
- 數(shù)據(jù)分片操作,如果分片鍵沒(méi)有在SQL或數(shù)據(jù)表中,而是在業(yè)務(wù)邏輯代碼中
- 讀寫分離操作,如果強(qiáng)制在主庫(kù)進(jìn)行某些數(shù)據(jù)操作
Sharding-JDBC強(qiáng)制路由案例實(shí)戰(zhàn)官方指導(dǎo)手冊(cè)
?? 二.Sharding-JDBC強(qiáng)制路由案例實(shí)戰(zhàn)
2.1 數(shù)據(jù)環(huán)境準(zhǔn)備
沒(méi)有創(chuàng)建過(guò)的同學(xué)們需要在 ljw_course_db1
和 ljw_course_db2
中創(chuàng)建 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 創(chuàng)建SpringBoot程序 - 導(dǎo)入依賴
引入依賴 (注意: 在這里使用ShardingSphere4.1版本為案例
進(jìn)行強(qiáng)制路由的實(shí)戰(zhàn))
<?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 創(chuàng)建SpringBoot程序 - 實(shí)體類
與數(shù)據(jù)庫(kù)表中對(duì)應(yīng)的實(shí)體類
@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 創(chuàng)建SpringBoot程序 - 數(shù)據(jù)庫(kù)Mapper接口 & 主啟動(dòng)類
編寫對(duì)應(yīng)的數(shù)據(jù)庫(kù)持久層CourseMapper接口
@Repository public interface CourseMapper extends BaseMapper<Course> { }
@Repository注解的類需要交給我們的Spring容器進(jìn)行管理,因此需要我們?cè)谥鲉?dòng)類加上掃描接口的注解。
@SpringBootApplication @MapperScan("com.ljw.mapper") public class ShardingSphereApplication { public static void main(String[] args) { SpringApplication.run(ShardingSphereApplication.class,args); } }
2.5 創(chuàng)建SpringBoot程序 - 自定義強(qiáng)制路由配置類
在自定義類中編寫分庫(kù)或分表路由策略,實(shí)現(xiàn)HintShardingAlgorithm接口,并且重寫doSharding方法
public class HintShardingAlgorithmConfig implements HintShardingAlgorithm<Long> { /** * 定義強(qiáng)制路由策略 * collection: 代表分片目標(biāo): 對(duì)哪些數(shù)據(jù)庫(kù) 表進(jìn)行分片,比如做分庫(kù)路由,集合中就存儲(chǔ)著 db1.t_course, db1.t_course * hintShardingValue: 代表分片值, 指的是使用者對(duì)分片鍵賦的值 */ @Override public Collection<String> doSharding(Collection<String> collection, HintShardingValue<Long> hintShardingValue) { // 結(jié)果收集 Collection<String> result = new ArrayList<>(); // 遍歷數(shù)據(jù)庫(kù) // collection: 代表分片目標(biāo): 對(duì)哪些數(shù)據(jù)庫(kù) 表進(jìn)行分片,比如做分庫(kù)路由,集合中就存儲(chǔ)著 db1.t_course, db1.t_course for (String actualDb : collection) { // hintShardingValue: 代表分片值, 指的是使用者對(duì)分片鍵賦的值 Collection<Long> values = hintShardingValue.getValues(); for (Long value : values) { //分庫(kù)路由 判斷當(dāng)前節(jié)點(diǎn)名稱結(jié)尾 是否與取模結(jié)果一致 if(actualDb.endsWith(String.valueOf(value % 2 + 1))){ result.add(actualDb); } } } return result; } }
2.6 創(chuàng)建SpringBoot程序 - 強(qiáng)制路由配置文件
配置讀寫分離相關(guān)配置的信息
# 應(yīng)用名稱 spring.application.name=sharding-jdbc-hint # 打印SQl spring.shardingsphere.props.sql-show=true # 定義多個(gè)數(shù)據(jù)源 spring.shardingsphere.datasource.names = db1,db2 # 數(shù)據(jù)源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 # 數(shù)據(jù)源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 # 配置默認(rèn)數(shù)據(jù)源db1 spring.shardingsphere.sharding.default-data-source-name=db1 # Hint強(qiáng)制路由 # 使用t_course表測(cè)試強(qiáng)制路由到庫(kù) spring.shardingsphere.sharding.tables.t_course.database-strategy.hint.algorithm-class-name=com.ljw.hint.HintShardingAlgorithmConfig # 強(qiáng)制路由到指定表 spring.shardingsphere.sharding.tables.t_course.table-strategy.hint.algorithm-class-name=com.ljw.hint.HintShardingAlgorithmConfig #配置數(shù)據(jù)節(jié)點(diǎn) 指定t_course邏輯表表的真實(shí)分布情況 spring.shardingsphere.sharding.tables.t_course.actual-data-nodes=db$->{1..2}.t_course_$->{1..2}
?? 三.Sharding-JDBC強(qiáng)制路由案例測(cè)試
先將我們數(shù)據(jù)庫(kù)中表中原來(lái)的數(shù)據(jù)都刪除掉,如果是新建的同學(xué)就不用了!
3.1 強(qiáng)制路由到庫(kù)測(cè)試
@Autowired private CourseMapper courseMapper; //測(cè)試強(qiáng)制路由 到指定庫(kù)的插入操作 @Test public void testInsertCourse(){ //通過(guò)hintManager指定執(zhí)行策略的分片鍵的值 HintManager hintManager = HintManager.getInstance(); //強(qiáng)制路由到db2,此時(shí)我們需要傳入1,因?yàn)槲覀兣渲妙惖倪壿嬍莢laue%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強(qiáng)制路由案例實(shí)戰(zhàn)"); course.setBrief("全網(wǎng)Sharding-JDBC強(qiáng)制路由案例實(shí)戰(zhàn)最詳細(xì)講解?。?!"); course.setPrice(8939.00); course.setStatus(0); courseMapper.insert(course); } }
運(yùn)行結(jié)果:
3.2 強(qiáng)制路由到庫(kù)到表測(cè)試
@Autowired private CourseMapper courseMapper; @Test public void testHintDbToTable(){ HintManager hintManager = HintManager.getInstance(); //強(qiáng)制路由到指定庫(kù) -> db2 hintManager.addDatabaseShardingValue("t_course",1L); //強(qiáng)制路由到指定表 ->course1 hintManager.addTableShardingValue("t_course",0L); List<Course> courses = courseMapper.selectList(null); courses.forEach(System.out::println); }
運(yùn)行結(jié)果:
?? 四.總結(jié)
本篇文章主要講解了Sharding-JDBC強(qiáng)制路由案例實(shí)戰(zhàn),實(shí)操過(guò)程非常重要,大家一定要?jiǎng)邮钟H自實(shí)踐一下,更多相關(guān)Sharding-JDBC強(qiáng)制路由內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于Java的二叉樹(shù)、紅黑樹(shù)、B+樹(shù)詳解
這篇文章主要介紹了關(guān)于Java的二叉樹(shù)、紅黑樹(shù)、B+樹(shù)詳解,能同時(shí)具備數(shù)組查找快的優(yōu)點(diǎn)以及鏈表插入和刪除快的優(yōu)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)就是樹(shù),需要的朋友可以參考下2023-05-05Java double轉(zhuǎn)BigDecimal的注意事項(xiàng)說(shuō)明
這篇文章主要介紹了Java double轉(zhuǎn)BigDecimal的注意事項(xiàng)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01Java中ArrayBlockingQueue和LinkedBlockingQueue
這篇文章主要介紹了Java中ArrayBlockingQueue和LinkedBlockingQueue,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-09-09Mybatis使用注解實(shí)現(xiàn)復(fù)雜動(dòng)態(tài)SQL的方法詳解
當(dāng)使用 MyBatis 注解方式執(zhí)行復(fù)雜 SQL 時(shí),你可以使用 @Select、@Update、@Insert、@Delete 注解直接在接口方法上編寫 SQL,本文給大家介紹了Mybatis如何使用注解實(shí)現(xiàn)復(fù)雜動(dòng)態(tài)SQL,文中有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下2023-12-12IDEA使用Maven創(chuàng)建父與子多模塊項(xiàng)目的圖文教程
在?IntelliJ?IDEA?中使用?Maven?創(chuàng)建父與子多模塊項(xiàng)目是一個(gè)常見(jiàn)的開(kāi)發(fā)實(shí)踐,有助于更好地組織和管理代碼,所以本文小編給大家介紹了IDEA使用Maven創(chuàng)建父與子多模塊項(xiàng)目的圖文教程,需要的小伙伴跟著小編一起來(lái)看看吧2025-03-03MyBatis Plus 將查詢結(jié)果封裝到指定實(shí)體的方法步驟
這篇文章主要介紹了MyBatis Plus 將查詢結(jié)果封裝到指定實(shí)體的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09關(guān)于maven依賴 ${xxx.version}報(bào)錯(cuò)問(wèn)題
這篇文章主要介紹了關(guān)于maven依賴 ${xxx.version}報(bào)錯(cuò)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01JFinal使用ajaxfileupload實(shí)現(xiàn)圖片上傳及預(yù)覽
這篇文章主要為大家詳細(xì)介紹了JFinal使用ajaxfileupload實(shí)現(xiàn)圖片上傳及預(yù)覽,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09