這次在上一篇的基礎上,這次用到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]
分庫 + 分表同時進行
核心配置
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= #加密器名字
后台原理
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/
全部源碼