SpringBoot集成Sharding-JDBC實現(xiàn)分庫分表方式
一、環(huán)境搭建
1.創(chuàng)建一個springboot項目,引入以下依賴。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.20</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.0.0-RC1</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.5</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
2.創(chuàng)建一個數(shù)據(jù)庫user和兩張表user_1,user_2
CREATE DATABASE `user`; CREATE TABLE `user_1` ( `id` bigint(30) NOT NULL, `username` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, `gender` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 CREATE TABLE `user_2` ( `id` bigint(30) NOT NULL, `username` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, `gender` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
3.分別創(chuàng)建user表對應的實體類和mapper
實體類代碼
@Data public class User { private Long id; private String username; private String password; private String gender; }
mapper代碼
public interface UserMapper extends BaseMapper<User>{ }
結構圖:
二、實現(xiàn)水平分表
需求:現(xiàn)在有兩個user表,一個是user_1,一個是user_2,當id為偶數(shù)的時候向user_1表中插入數(shù)據(jù),當id為奇數(shù)的時候向user_2表中插入數(shù)據(jù),實現(xiàn)水平分表。
1.配置application.properties
#指定當前應用的所有數(shù)據(jù)源標識(由于后期可能會涉及到多個數(shù)據(jù)源,或讀寫分離等,這里要為每個數(shù)據(jù)源 # 起一個標識名,然后為每個數(shù)據(jù)源具體配置) spring.shardingsphere.datasource.names=d1 #配置d1這個數(shù)據(jù)源,由于這里是水平分表,所以只需要一個數(shù)據(jù)源即可 其中d1代表該數(shù)據(jù)源的一個標識 spring.shardingsphere.datasource.d1.type=com.alibaba.druid.pool.DruidDataSource #指定鏈接驅動 spring.shardingsphere.datasource.d1.driver-class-name=com.mysql.cj.jdbc.Driver #指定鏈接url spring.shardingsphere.datasource.d1.url=jdbc:mysql://localhost:3308/user?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC #指定鏈接用戶名 spring.shardingsphere.datasource.d1.username=root #指定鏈接密碼 spring.shardingsphere.datasource.d1.password=root #由于是水平分表,所以會涉及到多張相同的表,這里指定這些表的分布情況:在哪個數(shù)據(jù)源上,以及一共有幾張表 #指定在d1數(shù)據(jù)源,且有user_1和user_2兩張表 #$->{1..2}該表達式是與前面的user_相拼接的,不能亂寫,例如我們現(xiàn)在的兩張表名是user_1和user_2,那這里就是user_$->{1..2} #如果我們分布了3張表 user_5,user_6,user_7,那這里就是user_$->{5..6..7} spring.shardingsphere.sharding.tables.user.actual-data-nodes=d1.user_$->{1..2} # 指定 user 表里面主鍵id 以及id的生成策略 SNOWFLAKE:表示用雪花算法生成該id spring.shardingsphere.sharding.tables.user.key-generator.column=id spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE # 指定分片策略 約定 id 值偶數(shù)添加到 user_1 表,如果 id 是奇數(shù)添加到 user_2表 #指定要根據(jù)哪個字段進行分表,這里根據(jù)id進行分表 spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id #執(zhí)行分表的規(guī)則:注意這里是$->{id% 2 + 1},由于偶數(shù)%2的結果為0,但是我們并沒有user_0這樣表 #所以我們要在取模的結果上+1 這樣就實現(xiàn)了如果是偶數(shù)那么取模的結果就是user_1,如果是奇數(shù)就是user_2 spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{id% 2 + 1} #開啟sql 輸出日志 spring.shardingsphere.props.sql.show=true # 由于一個實體類對應兩張表,所以會產(chǎn)生覆蓋操作,加上這個配置解決覆蓋問題 spring.main.allow-bean-definition-overriding=true
2.編寫測試代碼
@Test void testAddUser() { for (int i = 0;i < 6;i++){ User user = new User(); user.setGender("0"); user.setPassword(UUID.randomUUID().toString().substring(0,5)); user.setUsername("-->" + i); userMapper.insert(user); } }
3.日志查看:
可以看到當user_id的值為偶數(shù)的時候,是向user_1表中插入的。
再看當user_id的值為奇數(shù)的時候,該條數(shù)據(jù)插入了user_2這個表。
三、實現(xiàn)水平分庫
需求:現(xiàn)在有兩個user庫,一個是user_db1,一個是user_db2,每個user庫中都有兩張相同的表,user_1,user_2,當user對象的gender屬性值為1的時候向user_db1庫中插入,當user對象的gender屬性值為0的時候向user_db2庫中插入,這是分庫的規(guī)則,分表的規(guī)則是,當id為偶數(shù)的時候向user_1表中插入數(shù)據(jù),當id為奇數(shù)的時候向user_2表中插入數(shù)據(jù)。(建表語句和上面是相同的)
結構如下:
2.配置application.properties
#指定當前應用的所有數(shù)據(jù)源標識(由于后期可能會涉及到多個數(shù)據(jù)源,或讀寫分離等,這里要為每個數(shù)據(jù)源 # 起一個標識名,然后為每個數(shù)據(jù)源具體配置) spring.shardingsphere.datasource.names=d1,d2 #配置d1這個數(shù)據(jù)源,由于這里是水平分表,所以只需要一個數(shù)據(jù)源即可 其中d1代表該數(shù)據(jù)源的一個標識 spring.shardingsphere.datasource.d1.type=com.alibaba.druid.pool.DruidDataSource #指定鏈接驅動 spring.shardingsphere.datasource.d1.driver-class-name=com.mysql.cj.jdbc.Driver #指定鏈接url spring.shardingsphere.datasource.d1.url=jdbc:mysql://localhost:3308/user_db1?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC #指定鏈接用戶名 spring.shardingsphere.datasource.d1.username=root #指定鏈接密碼 spring.shardingsphere.datasource.d1.password=root #由于是兩個數(shù)據(jù)庫,所以要配置兩個數(shù)據(jù)源 #配置d2數(shù)據(jù)源 spring.shardingsphere.datasource.d2.type=com.alibaba.druid.pool.DruidDataSource #指定鏈接驅動 spring.shardingsphere.datasource.d2.driver-class-name=com.mysql.cj.jdbc.Driver #指定鏈接url spring.shardingsphere.datasource.d2.url=jdbc:mysql://localhost:3308/user_db2?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC #指定鏈接用戶名 spring.shardingsphere.datasource.d2.username=root #指定鏈接密碼 spring.shardingsphere.datasource.d2.password=root #指定數(shù)據(jù)庫和表的分布情況 #指定數(shù)據(jù)庫分布情況,數(shù)據(jù)庫里面表分布情況 #d$->{1..2}.user_$->{1..2} 表示在d1,d2數(shù)據(jù)源上都有user_1和user_2兩張表 spring.shardingsphere.sharding.tables.user.actual-data-nodes=d$->{1..2}.user_$->{1..2} # 指定 user 表里面主鍵id 以及id的生成策略 SNOWFLAKE:表示用雪花算法生成該id spring.shardingsphere.sharding.tables.user.key-generator.column=id spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE # 指定分片策略 約定 id 值偶數(shù)添加到 user_1 表,如果 id 是奇數(shù)添加到 user_2表 #指定要根據(jù)哪個字段進行分表,這里根據(jù)id進行分表 spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id #執(zhí)行分表的規(guī)則:注意這里是$->{id% 2 + 1},由于偶數(shù)%2的結果為0,但是我們并沒有user_0這樣表 #所以我們要在取模的結果上+1 這樣就實現(xiàn)了如果是偶數(shù)那么取模的結果就是user_1,如果是奇數(shù)就是user_2 spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{id% 2 + 1} #============================================================================================ #以上指定了分表策略,下面指定分庫策略,也就是gender為0則向user_db1中插入,為1則向user_db2中插入 spring.shardingsphere.sharding.tables.user.database-strategy.inline..sharding-column=gender #如果gender為0 則表達式{gender=='0'?1:2}的結果就是1,則d$->{gender=='0'?1:2} = d1,就會向d1數(shù)據(jù)源也就是user_db1庫中添加 #如果gender為1 則表達式{gender=='0'?1:2}的結果就是2,則d$->{gender=='0'?1:2} = d2,就會向d1數(shù)據(jù)源也就是user_db2庫中添加 spring.shardingsphere.sharding.tables.user.database-strategy.inline.algorithm-expression=d$->{gender=='0'?1:2} #開啟sql 輸出日志 spring.shardingsphere.props.sql.show=true # 由于一個實體類對應兩張表,所以會產(chǎn)生覆蓋操作,加上這個配置解決覆蓋問題 spring.main.allow-bean-definition-overriding=true
2.編寫測試代碼
@Test void testAddUser() { for (int i = 0;i < 10;i++){ User user = new User(); user.setPassword(UUID.randomUUID().toString().substring(0,5)); user.setUsername("-->" + i); if (i % 2 == 0) user.setGender("0"); else user.setGender("1"); userMapper.insert(user); } }
3.數(shù)據(jù)庫查看
可以看到:gender為0,且id為偶數(shù)插入到了user_db1庫中的,user_1表。
可以看到:gender為0,且id為奇數(shù)插入到了user_db1庫中的,user_2表。
可以看到:gender為1,且id為偶數(shù)插入到了user_db2庫中的,user_1表。
可以看到:gender為1,且id為奇數(shù)插入到了user_db2庫中的,user_2表。
四、公共表的配置
有些表的數(shù)據(jù)量不大,需要在每個數(shù)據(jù)庫中都有,這時需要配置公共表。
向user_db1,和user_db2兩個數(shù)據(jù)庫都創(chuàng)建一個t_dict表
CREATE table t_dicit( id BIGINT(30) PRIMARY key, `dstatus` VARCHAR(255) not null, `description` VARCHAR(255) not null )
status和desc是mysql的兩個關鍵字,表的字段名盡量避開這些關鍵字,否則會發(fā)生運行時異常。
1.配置application.properties
#指定當前應用的所有數(shù)據(jù)源標識(由于后期可能會涉及到多個數(shù)據(jù)源,或讀寫分離等,這里要為每個數(shù)據(jù)源 # 起一個標識名,然后為每個數(shù)據(jù)源具體配置) spring.shardingsphere.datasource.names=d1,d2 #配置d1這個數(shù)據(jù)源,由于這里是水平分表,所以只需要一個數(shù)據(jù)源即可 其中d1代表該數(shù)據(jù)源的一個標識 spring.shardingsphere.datasource.d1.type=com.alibaba.druid.pool.DruidDataSource #指定鏈接驅動 spring.shardingsphere.datasource.d1.driver-class-name=com.mysql.cj.jdbc.Driver #指定鏈接url spring.shardingsphere.datasource.d1.url=jdbc:mysql://localhost:3308/user_db1?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC #指定鏈接用戶名 spring.shardingsphere.datasource.d1.username=root #指定鏈接密碼 spring.shardingsphere.datasource.d1.password=root #由于是兩個數(shù)據(jù)庫,所以要配置兩個數(shù)據(jù)源 #配置d2數(shù)據(jù)源 spring.shardingsphere.datasource.d2.type=com.alibaba.druid.pool.DruidDataSource #指定鏈接驅動 spring.shardingsphere.datasource.d2.driver-class-name=com.mysql.cj.jdbc.Driver #指定鏈接url spring.shardingsphere.datasource.d2.url=jdbc:mysql://localhost:3308/user_db2?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC #指定鏈接用戶名 spring.shardingsphere.datasource.d2.username=root #指定鏈接密碼 spring.shardingsphere.datasource.d2.password=root #指定數(shù)據(jù)庫和表的分布情況 #指定數(shù)據(jù)庫分布情況,數(shù)據(jù)庫里面表分布情況 #d$->{1..2}.user_$->{1..2} 表示在d1,d2數(shù)據(jù)源上都有user_1和user_2兩張表 spring.shardingsphere.sharding.tables.user.actual-data-nodes=d$->{1..2}.user_$->{1..2} # 指定 user 表里面主鍵id 以及id的生成策略 SNOWFLAKE:表示用雪花算法生成該id spring.shardingsphere.sharding.tables.user.key-generator.column=id spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE # 指定分片策略 約定 id 值偶數(shù)添加到 user_1 表,如果 id 是奇數(shù)添加到 user_2表 #指定要根據(jù)哪個字段進行分表,這里根據(jù)id進行分表 spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id #執(zhí)行分表的規(guī)則:注意這里是$->{id% 2 + 1},由于偶數(shù)%2的結果為0,但是我們并沒有user_0這樣表 #所以我們要在取模的結果上+1 這樣就實現(xiàn)了如果是偶數(shù)那么取模的結果就是user_1,如果是奇數(shù)就是user_2 spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{id% 2 + 1} #============================================================================================ #以上指定了分表策略,下面指定分庫策略,也就是gender為0則向user_db1中插入,為1則向user_db2中插入 spring.shardingsphere.sharding.tables.user.database-strategy.inline..sharding-column=gender #如果gender為0 則表達式{gender=='0'?1:2}的結果就是1,則d$->{gender=='0'?1:2} = d1,就會向d1數(shù)據(jù)源也就是user_db1庫中添加 #如果gender為1 則表達式{gender=='0'?1:2}的結果就是2,則d$->{gender=='0'?1:2} = d2,就會向d1數(shù)據(jù)源也就是user_db2庫中添加 spring.shardingsphere.sharding.tables.user.database-strategy.inline.algorithm-expression=d$->{gender=='0'?1:2} #============================================================================================ #配置公共表 在向t_dicit表插入數(shù)據(jù)時 這些默認的數(shù)據(jù)源(d1,d2)的t_dicit表都會插入該數(shù)據(jù) spring.shardingsphere.sharding.broadcast-tables=t_dicit spring.shardingsphere.sharding.tables.t_dicit.key-generator.column=id spring.shardingsphere.sharding.tables.t_dicit.key-generator.type=SNOWFLAKE #開啟sql 輸出日志 spring.shardingsphere.props.sql.show=true # 由于一個實體類對應兩張表,所以會產(chǎn)生覆蓋操作,加上這個配置解決覆蓋問題 spring.main.allow-bean-definition-overriding=true
2.編寫實體類和mapper
@TableName("t_dicit") @Data public class Dict { @TableId private Long id; private String dstatus; private String description; }
public interface DictMapper extends BaseMapper<Dict> { }
3.編寫測試程序
@Test public void testDict(){ Dict dict = new Dict(); dict.setDescription("啟用狀態(tài)"); dict.setDstatus("A"); dictMapper.insert(dict); }
4.查看日志發(fā)現(xiàn)分別向兩個數(shù)據(jù)源發(fā)送了sql
5.查看表
兩個庫的t_dicit表都有了該數(shù)據(jù)。
同樣如果是刪除公共表的數(shù)據(jù)也是同時將兩個數(shù)據(jù)庫中的記錄刪除。
@Test public void testDictDel(){ dictMapper.deleteById(1270356973266165762L); }
運行日志:
兩個庫中的數(shù)據(jù)都被刪除。
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
使用arthas命令redefine實現(xiàn)Java熱更新(推薦)
今天分享一個非常重要的命令 redefine ,主要作用是加載外部的 .class 文件,用來替換 JVM 已經(jīng)加載的類,總結起來就是實現(xiàn)了 Java 的熱更新,感興趣的朋友跟隨小編一起看看吧2020-05-05Mybatis如何傳入多個參數(shù)的實現(xiàn)代碼
這篇文章主要介紹了Mybatis如何傳入多個參數(shù)的實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-12-12Java中計算集合中元素的出現(xiàn)次數(shù)統(tǒng)計
本文主要介紹了Java中計算集合中元素的出現(xiàn)次數(shù)統(tǒng)計,使用Collections類配合HashMap來統(tǒng)計和java lamb 計算這兩種方式,具有一定的參考價值,感興趣可以了解一下2024-02-02Spring-boot oauth2使用RestTemplate進行后臺自動登錄的實現(xiàn)
這篇文章主要介紹了Spring-boot oauth2使用RestTemplate進行后臺自動登錄的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-07-07