SpringBoot結合ShardingSphere實現分庫分表、讀寫分離


這次在上一篇的基礎上,這次用到4個庫,將庫db0、db1各增加一個從庫dbS0\dbS1

四個庫再執行腳本:

-- ----------------------------
-- Table structure for `user0`
-- ----------------------------
DROP TABLE IF EXISTS `user0`;
CREATE TABLE `user0` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=105 DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of user0
-- ----------------------------
INSERT INTO `user0` VALUES ('1', 'wangxin02', '99');

-- ----------------------------
-- Table structure for `user1`
-- ----------------------------
DROP TABLE IF EXISTS `user1`;
CREATE TABLE `user1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of user1
-- ----------------------------
INSERT INTO `user1` VALUES ('1', 'wangxin', '99');

只分表不分庫

首先先只分表不分庫,使用master來執行寫操作

核心配置

#數據分表規則--僅分表不分庫
#注意:tables.user中的user是邏輯表
#指定所需分的表,分user1、user2
spring.shardingsphere.sharding.tables.user.actual-data-nodes=master.user$->{0..1}

#行表達式分片策略
spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id
#分表兩個,所以規則為主鍵除以2取模
spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user$->{id % 2}

##用於單分片鍵的標准分片場景
##指定自增主鍵
#spring.shardingsphere.sharding.tables.user.key-generator.column= id
##自增列值生成器類型,缺省表示使用默認自增列值生成器。可使用用戶自定義的列值生成器或選擇內置類型:SNOWFLAKE/UUID
#spring.shardingsphere.sharding.tables.user.key-generator.type= SNOWFLAKE

map新增

  <insert id="insertSharding" parameterType="com.xin.shardingspherejdbcdemo.entity.User">
    insert into user (id,name, age)
    values ( #{id,jdbcType=INTEGER},#{name,jdbcType=VARCHAR},
      #{age,jdbcType=INTEGER})
  </insert>

控制器新增

@GetMapping("/saveUserShardingOnlyTable")
    public void saveUserShardingOnlyTable() {
        List<User> userList = Lists.newArrayList();
        userList.add(new User(100,"用戶1",  31));
        userList.add(new User(101,"用戶2",  30));
        userList.add(new User(102,"用戶3",  28));
        userList.add(new User(103,"用戶4",  64));
        userList.add(new User(104,"用戶5",  62));
        userList.add(new User(105,"用戶6",  16));
        for (User u : userList){
            userService.saveSharding(u);
        }
    }

執行saveUserShardingOnlyTable后,我們發現db0中的兩個表分別加入了3條記錄

user0加入:

100 用戶1 31
102 用戶3 28
104 用戶5 62

user1加入:
101 用戶2 30
103 用戶4 64
105 用戶6 16

日志:

2020-05-22 14:33:33.807 INFO 9952 --- [nio-8086-exec-1] ShardingSphere-SQL : Actual SQL: master ::: insert into user0 (id,name, age)
values (?, ?, ?) ::: [100, 用戶1, 31]
2020-05-22 14:33:33.944 INFO 9952 --- [nio-8086-exec-1] ShardingSphere-SQL : Rule Type: sharding
2020-05-22 14:33:33.945 INFO 9952 --- [nio-8086-exec-1] ShardingSphere-SQL : Logic SQL: insert into user (id,name, age)
values ( ?,?,
?)
2020-05-22 14:33:33.945 INFO 9952 --- [nio-8086-exec-1] ShardingSphere-SQL : SQLStatement: InsertSQLStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.InsertStatement@8a9d30d, tablesContext=TablesContext(tables=[Table(name=user, alias=Optional.absent())], schema=Optional.absent())), columnNames=[id, name, age], insertValueContexts=[InsertValueContext(parametersCount=3, valueExpressions=[ParameterMarkerExpressionSegment(startIndex=45, stopIndex=45, parameterMarkerIndex=0), ParameterMarkerExpressionSegment(startIndex=47, stopIndex=47, parameterMarkerIndex=1), ParameterMarkerExpressionSegment(startIndex=56, stopIndex=56, parameterMarkerIndex=2)], parameters=[101, 用戶2, 30])])
2020-05-22 14:33:33.945 INFO 9952 --- [nio-8086-exec-1] ShardingSphere-SQL : Actual SQL: master ::: insert into user1 (id,name, age)
values (?, ?, ?) ::: [101, 用戶2, 30]
2020-05-22 14:33:33.985 INFO 9952 --- [nio-8086-exec-1] ShardingSphere-SQL : Rule Type: sharding
2020-05-22 14:33:33.985 INFO 9952 --- [nio-8086-exec-1] ShardingSphere-SQL : Logic SQL: insert into user (id,name, age)
values ( ?,?,
?)
2020-05-22 14:33:33.985 INFO 9952 --- [nio-8086-exec-1] ShardingSphere-SQL : SQLStatement: InsertSQLStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.InsertStatement@8a9d30d, tablesContext=TablesContext(tables=[Table(name=user, alias=Optional.absent())], schema=Optional.absent())), columnNames=[id, name, age], insertValueContexts=[InsertValueContext(parametersCount=3, valueExpressions=[ParameterMarkerExpressionSegment(startIndex=45, stopIndex=45, parameterMarkerIndex=0), ParameterMarkerExpressionSegment(startIndex=47, stopIndex=47, parameterMarkerIndex=1), ParameterMarkerExpressionSegment(startIndex=56, stopIndex=56, parameterMarkerIndex=2)], parameters=[102, 用戶3, 28])])
2020-05-22 14:33:33.985 INFO 9952 --- [nio-8086-exec-1] ShardingSphere-SQL : Actual SQL: master ::: insert into user0 (id,name, age)
values (?, ?, ?) ::: [102, 用戶3, 28]
2020-05-22 14:33:34.043 INFO 9952 --- [nio-8086-exec-1] ShardingSphere-SQL : Rule Type: sharding
2020-05-22 14:33:34.043 INFO 9952 --- [nio-8086-exec-1] ShardingSphere-SQL : Logic SQL: insert into user (id,name, age)
values ( ?,?,
?)
2020-05-22 14:33:34.043 INFO 9952 --- [nio-8086-exec-1] ShardingSphere-SQL : SQLStatement: InsertSQLStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.InsertStatement@8a9d30d, tablesContext=TablesContext(tables=[Table(name=user, alias=Optional.absent())], schema=Optional.absent())), columnNames=[id, name, age], insertValueContexts=[InsertValueContext(parametersCount=3, valueExpressions=[ParameterMarkerExpressionSegment(startIndex=45, stopIndex=45, parameterMarkerIndex=0), ParameterMarkerExpressionSegment(startIndex=47, stopIndex=47, parameterMarkerIndex=1), ParameterMarkerExpressionSegment(startIndex=56, stopIndex=56, parameterMarkerIndex=2)], parameters=[103, 用戶4, 64])])
2020-05-22 14:33:34.043 INFO 9952 --- [nio-8086-exec-1] ShardingSphere-SQL : Actual SQL: master ::: insert into user1 (id,name, age)
values (?, ?, ?) ::: [103, 用戶4, 64]
View Code

 

分庫 + 分表同時進行

核心配置

server.port=8086

#指定mybatis信息
mybatis.config-location=classpath:mybatis-config.xml

# 數據源 主庫、從庫 -- 讀寫分離
#spring.shardingsphere.datasource.names=master,slave0
# 數據源 主庫 --僅分表不分庫
#spring.shardingsphere.datasource.names=master
# 數據源 主庫db0、主庫db1 -- 分庫分表
spring.shardingsphere.datasource.names=master0,master1


# 數據源 主庫
spring.shardingsphere.datasource.master0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.master0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master0.url=jdbc:mysql://localhost:3307/db0?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.master0.username=root
spring.shardingsphere.datasource.master0.password=mysql

# 數據源 主庫
spring.shardingsphere.datasource.master1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.master1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master1.url=jdbc:mysql://localhost:3307/db1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.master1.username=root
spring.shardingsphere.datasource.master1.password=mysql

# 數據源 從庫
spring.shardingsphere.datasource.slave0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.slave0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave0.url=jdbc:mysql://localhost:3307/db1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.slave0.username=root
spring.shardingsphere.datasource.slave0.password=mysql

## 讀寫分離
##spring.shardingsphere.masterslave.load-balance-algorithm-type=round_robin
#spring.shardingsphere.masterslave.name=ms
#spring.shardingsphere.masterslave.master-data-source-name=master
#spring.shardingsphere.masterslave.slave-data-source-names=slave0

## 分庫
#根據ID分庫
#spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=id
#spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=master$->{id % 2}

#根據年齡分庫
spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=age
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=master$->{age > 30?0:1}

#數據分表規則--僅分表不分庫
#注意:tables.user中的user是邏輯表
#僅分表時使用,單一寫表,指定所需分的表,分user1、user2
#spring.shardingsphere.sharding.tables.user.actual-data-nodes=master.user$->{0..1}
#同時分庫分表時使用
spring.shardingsphere.sharding.tables.user.actual-data-nodes=master$->{0..1}.user$->{0..1}

#行表達式分片策略
spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id
#分表兩個,所以規則為主鍵除以2取模
spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user$->{id % 2}

##用於單分片鍵的標准分片場景
##指定自增主鍵
#spring.shardingsphere.sharding.tables.user.key-generator.column= id
##自增列值生成器類型,缺省表示使用默認自增列值生成器。可使用用戶自定義的列值生成器或選擇內置類型:SNOWFLAKE/UUID
#spring.shardingsphere.sharding.tables.user.key-generator.type= SNOWFLAKE

#打印sql
spring.shardingsphere.props.sql.show=true

控制器

    @GetMapping("/saveUserShardingDBwithTable")
    public void saveUserShardingDBwithTable() {
        List<User> userList = Lists.newArrayList();
        userList.add(new User(10000,"用戶1",  31));
        userList.add(new User(10001,"用戶2",  30));
        userList.add(new User(10002,"用戶3",  28));
        userList.add(new User(10003,"用戶4",  64));
        userList.add(new User(10004,"用戶5",  62));
        userList.add(new User(10005,"用戶6",  16));
        for (User u : userList){
            userService.saveSharding(u);
        }
    }

 

分庫分表+讀寫分離

只需要在上面的基礎上添加讀寫分離的配置即可

#指定master0為主庫,slave0為它的從庫
spring.shardingsphere.sharding.master-slave-rules.master0.master-data-source-name=master0
spring.shardingsphere.sharding.master-slave-rules.master0.slave-data-source-names=slave0
#指定master1為主庫,slave1為它的從庫
spring.shardingsphere.sharding.master-slave-rules.master1.master-data-source-name=master1
spring.shardingsphere.sharding.master-slave-rules.master1.slave-data-source-names=slave1

完整配置說明

數據分片
spring.shardingsphere.datasource.names= #數據源名稱,多數據源以逗號分隔

spring.shardingsphere.datasource.<data-source-name>.type= #數據庫連接池類名稱
spring.shardingsphere.datasource.<data-source-name>.driver-class-name= #數據庫驅動類名
spring.shardingsphere.datasource.<data-source-name>.url= #數據庫url連接
spring.shardingsphere.datasource.<data-source-name>.username= #數據庫用戶名
spring.shardingsphere.datasource.<data-source-name>.password= #數據庫密碼
spring.shardingsphere.datasource.<data-source-name>.xxx= #數據庫連接池的其它屬性

spring.shardingsphere.sharding.tables.<logic-table-name>.actual-data-nodes= #由數據源名 + 表名組成,以小數點分隔。多個表以逗號分隔,支持inline表達式。缺省表示使用已知數據源與邏輯表名稱生成數據節點,用於廣播表(即每個庫中都需要一個同樣的表用於關聯查詢,多為字典表)或只分庫不分表且所有庫的表結構完全一致的情況

#分庫策略,缺省表示使用默認分庫策略,以下的分片策略只能選其一

#用於單分片鍵的標准分片場景
spring.shardingsphere.sharding.tables.<logic-table-name>.database-strategy.standard.sharding-column= #分片列名稱
spring.shardingsphere.sharding.tables.<logic-table-name>.database-strategy.standard.precise-algorithm-class-name= #精確分片算法類名稱,用於=和IN。該類需實現PreciseShardingAlgorithm接口並提供無參數的構造器
spring.shardingsphere.sharding.tables.<logic-table-name>.database-strategy.standard.range-algorithm-class-name= #范圍分片算法類名稱,用於BETWEEN,可選。該類需實現RangeShardingAlgorithm接口並提供無參數的構造器

#用於多分片鍵的復合分片場景
spring.shardingsphere.sharding.tables.<logic-table-name>.database-strategy.complex.sharding-columns= #分片列名稱,多個列以逗號分隔
spring.shardingsphere.sharding.tables.<logic-table-name>.database-strategy.complex.algorithm-class-name= #復合分片算法類名稱。該類需實現ComplexKeysShardingAlgorithm接口並提供無參數的構造器

#行表達式分片策略
spring.shardingsphere.sharding.tables.<logic-table-name>.database-strategy.inline.sharding-column= #分片列名稱
spring.shardingsphere.sharding.tables.<logic-table-name>.database-strategy.inline.algorithm-expression= #分片算法行表達式,需符合groovy語法

#Hint分片策略
spring.shardingsphere.sharding.tables.<logic-table-name>.database-strategy.hint.algorithm-class-name= #Hint分片算法類名稱。該類需實現HintShardingAlgorithm接口並提供無參數的構造器

#分表策略,同分庫策略
spring.shardingsphere.sharding.tables.<logic-table-name>.table-strategy.xxx= #省略

spring.shardingsphere.sharding.tables.<logic-table-name>.key-generator.column= #自增列名稱,缺省表示不使用自增主鍵生成器
spring.shardingsphere.sharding.tables.<logic-table-name>.key-generator.type= #自增列值生成器類型,缺省表示使用默認自增列值生成器。可使用用戶自定義的列值生成器或選擇內置類型:SNOWFLAKE/UUID
spring.shardingsphere.sharding.tables.<logic-table-name>.key-generator.props.<property-name>= #屬性配置, 注意:使用SNOWFLAKE算法,需要配置worker.id與max.tolerate.time.difference.milliseconds屬性。若使用此算法生成值作分片值,建議配置max.vibration.offset屬性

spring.shardingsphere.sharding.binding-tables[0]= #綁定表規則列表
spring.shardingsphere.sharding.binding-tables[1]= #綁定表規則列表
spring.shardingsphere.sharding.binding-tables[x]= #綁定表規則列表

spring.shardingsphere.sharding.broadcast-tables[0]= #廣播表規則列表
spring.shardingsphere.sharding.broadcast-tables[1]= #廣播表規則列表
spring.shardingsphere.sharding.broadcast-tables[x]= #廣播表規則列表

spring.shardingsphere.sharding.default-data-source-name= #未配置分片規則的表將通過默認數據源定位
spring.shardingsphere.sharding.default-database-strategy.xxx= #默認數據庫分片策略,同分庫策略
spring.shardingsphere.sharding.default-table-strategy.xxx= #默認表分片策略,同分表策略
spring.shardingsphere.sharding.default-key-generator.type= #默認自增列值生成器類型,缺省將使用org.apache.shardingsphere.core.keygen.generator.impl.SnowflakeKeyGenerator。可使用用戶自定義的列值生成器或選擇內置類型:SNOWFLAKE/UUID
spring.shardingsphere.sharding.default-key-generator.props.<property-name>= #自增列值生成器屬性配置, 比如SNOWFLAKE算法的worker.id與max.tolerate.time.difference.milliseconds

spring.shardingsphere.sharding.master-slave-rules.<master-slave-data-source-name>.master-data-source-name= #詳見讀寫分離部分
spring.shardingsphere.sharding.master-slave-rules.<master-slave-data-source-name>.slave-data-source-names[0]= #詳見讀寫分離部分
spring.shardingsphere.sharding.master-slave-rules.<master-slave-data-source-name>.slave-data-source-names[1]= #詳見讀寫分離部分
spring.shardingsphere.sharding.master-slave-rules.<master-slave-data-source-name>.slave-data-source-names[x]= #詳見讀寫分離部分
spring.shardingsphere.sharding.master-slave-rules.<master-slave-data-source-name>.load-balance-algorithm-class-name= #詳見讀寫分離部分
spring.shardingsphere.sharding.master-slave-rules.<master-slave-data-source-name>.load-balance-algorithm-type= #詳見讀寫分離部分

spring.shardingsphere.props.sql.show= #是否開啟SQL顯示,默認值: false
spring.shardingsphere.props.executor.size= #工作線程數量,默認值: CPU核數
讀寫分離
#省略數據源配置,與數據分片一致

spring.shardingsphere.sharding.master-slave-rules.<master-slave-data-source-name>.master-data-source-name= #主庫數據源名稱
spring.shardingsphere.sharding.master-slave-rules.<master-slave-data-source-name>.slave-data-source-names[0]= #從庫數據源名稱列表
spring.shardingsphere.sharding.master-slave-rules.<master-slave-data-source-name>.slave-data-source-names[1]= #從庫數據源名稱列表
spring.shardingsphere.sharding.master-slave-rules.<master-slave-data-source-name>.slave-data-source-names[x]= #從庫數據源名稱列表
spring.shardingsphere.sharding.master-slave-rules.<master-slave-data-source-name>.load-balance-algorithm-class-name= #從庫負載均衡算法類名稱。該類需實現MasterSlaveLoadBalanceAlgorithm接口且提供無參數構造器
spring.shardingsphere.sharding.master-slave-rules.<master-slave-data-source-name>.load-balance-algorithm-type= #從庫負載均衡算法類型,可選值:ROUND_ROBIN,RANDOM。若`load-balance-algorithm-class-name`存在則忽略該配置

spring.shardingsphere.props.sql.show= #是否開啟SQL顯示,默認值: false
spring.shardingsphere.props.executor.size= #工作線程數量,默認值: CPU核數
spring.shardingsphere.props.check.table.metadata.enabled= #是否在啟動時檢查分表元數據一致性,默認值: false
數據脫敏
#省略數據源配置,與數據分片一致

spring.shardingsphere.encrypt.encryptors.<encryptor-name>.type= #加解密器類型,可自定義或選擇內置類型:MD5/AES 
spring.shardingsphere.encrypt.encryptors.<encryptor-name>.props.<property-name>= #屬性配置, 注意:使用AES加密器,需要配置AES加密器的KEY屬性:aes.key.value
spring.shardingsphere.encrypt.tables.<table-name>.columns.<logic-column-name>.plainColumn= #存儲明文的字段
spring.shardingsphere.encrypt.tables.<table-name>.columns.<logic-column-name>.cipherColumn= #存儲密文的字段
spring.shardingsphere.encrypt.tables.<table-name>.columns.<logic-column-name>.assistedQueryColumn= #輔助查詢字段,針對ShardingQueryAssistedEncryptor類型的加解密器進行輔助查詢
spring.shardingsphere.encrypt.tables.<table-name>.columns.<logic-column-name>.encryptor= #加密器名字
View Code

 后台原理

ShardingSphere的核心由SQL解析 => 執行器優化 => SQL路由 => SQL改寫 => SQL執行 => 結果歸並的流程組成。

SQL解析

分為詞法解析和語法解析。 先通過詞法解析器將SQL拆分為一個個不可再分的單詞。再使用語法解析器對SQL進行理解,並最終提煉出解析上下文。 解析上下文包括表、選擇項、排序項、分組項、聚合函數、分頁信息、查詢條件以及可能需要修改的占位符的標記。

執行器優化

合並和優化分片條件,如OR等。

SQL路由

根據解析上下文匹配用戶配置的分片策略,並生成路由路徑。目前支持分片路由和廣播路由。

SQL改寫

將SQL改寫為在真實數據庫中可以正確執行的語句。SQL改寫分為正確性改寫和優化改寫。

SQL執行

通過多線程執行器異步執行。

結果歸並

將多個執行結果集歸並以便於通過統一的JDBC接口輸出。結果歸並包括流式歸並、內存歸並和使用裝飾者模式的追加歸並這幾種方式。

具體見:https://shardingsphere.apache.org/document/current/cn/features/sharding/principle/

 

全部源碼

shardingsphere-jdbc-demo-all


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM