一、环境准备

1.数据库

创建2个库2个表:

  • xdclass_shop_order_0

    • product_order_0
    • product_order_1
    • ad_config
    • product_order_item_0
    • product_order_item_1
  • xdclass_shop_order_1
    • product_order_0
    • product_order_1
    • ad_config
    • product_order_item_0
    • product_order_item_1

数据库脚本:

  1. CREATE TABLE `product_order_0` (
  2. `id` bigint NOT NULL AUTO_INCREMENT,
  3. `out_trade_no` varchar(64) DEFAULT NULL COMMENT '订单唯一标识',
  4. `state` varchar(11) DEFAULT NULL COMMENT 'NEW 未支付订单,PAY已经支付订单,CANCEL超时取消订单',
  5. `create_time` datetime DEFAULT NULL COMMENT '订单生成时间',
  6. `pay_amount` decimal(16,2) DEFAULT NULL COMMENT '订单实际支付价格',
  7. `nickname` varchar(64) DEFAULT NULL COMMENT '昵称',
  8. `user_id` bigint DEFAULT NULL COMMENT '用户id',
  9. PRIMARY KEY (`id`)
  10. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
  11. CREATE TABLE `ad_config` (
  12. `id` bigint unsigned NOT NULL COMMENT '主键id',
  13. `config_key` varchar(1024) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '配置key',
  14. `config_value` varchar(1024) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '配置value',
  15. `type` varchar(128) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '类型',
  16. PRIMARY KEY (`id`)
  17. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
  18. CREATE TABLE `product_order_item_0` (
  19. `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  20. `product_order_id` bigint DEFAULT NULL COMMENT '订单号',
  21. `product_id` bigint DEFAULT NULL COMMENT '产品id',
  22. `product_name` varchar(128) DEFAULT NULL COMMENT '商品名称',
  23. `buy_num` int DEFAULT NULL COMMENT '购买数量',
  24. `user_id` bigint DEFAULT NULL,
  25. PRIMARY KEY (`id`)
  26. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

2.代码工程

1.工程创建

  1. 创建Maven工程,添加相关Maven依赖,
  1. <properties>
  2. <java.version>1.8</java.version>
  3. <maven.compiler.source>11</maven.compiler.source>
  4. <maven.compiler.target>11</maven.compiler.target>
  5. <spring.boot.version>2.5.5</spring.boot.version>
  6. <mybatisplus.boot.starter.version>3.4.0</mybatisplus.boot.starter.version>
  7. <lombok.version>1.18.16</lombok.version>
  8. <sharding-jdbc.version>4.1.1</sharding-jdbc.version>
  9. <junit.version>4.12</junit.version>
  10. <druid.version>1.1.16</druid.version>
  11. <!--跳过单元测试-->
  12. <skipTests>true</skipTests>
  13. </properties>
  14. <dependencies>
  15. <dependency>
  16. <groupId>org.springframework.boot</groupId>
  17. <artifactId>spring-boot-starter-web</artifactId>
  18. <version>${spring.boot.version}</version>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-test</artifactId>
  23. <version>${spring.boot.version}</version>
  24. <scope>test</scope>
  25. </dependency>
  26. <!--mybatis plus和springboot整合-->
  27. <dependency>
  28. <groupId>com.baomidou</groupId>
  29. <artifactId>mybatis-plus-boot-starter</artifactId>
  30. <version>${mybatisplus.boot.starter.version}</version>
  31. </dependency>
  32. <!-- mysql数据库 -->
  33. <dependency>
  34. <groupId>mysql</groupId>
  35. <artifactId>mysql-connector-java</artifactId>
  36. <version>8.0.27</version>
  37. </dependency>
  38. <dependency>
  39. <groupId>org.projectlombok</groupId>
  40. <artifactId>lombok</artifactId>
  41. <version>${lombok.version}</version>
  42. <!--<scope>provided</scope>-->
  43. </dependency>
  44. <!-- shardingshpere-jdbc-->
  45. <dependency>
  46. <groupId>org.apache.shardingsphere</groupId>
  47. <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
  48. <version>${sharding-jdbc.version}</version>
  49. </dependency>
  50. <dependency>
  51. <groupId>junit</groupId>
  52. <artifactId>junit</artifactId>
  53. <version>${junit.version}</version>
  54. </dependency>
  55. </dependencies>
  56. <build>
  57. <plugins>
  58. <plugin>
  59. <groupId>org.springframework.boot</groupId>
  60. <artifactId>spring-boot-maven-plugin</artifactId>
  61. <version>${spring.boot.version}</version>
  62. <configuration>
  63. <fork>true</fork>
  64. <addResources>true</addResources>
  65. </configuration>
  66. </plugin>
  67. </plugins>
  68. </build>
  1. 添加数据库配置文件,根据配置文件可知,配置了两个数据库ds0,ds1;
  1. spring.application.name=yb-sharding-jdbc
  2. server.port=8080
  3. logging.level.root=INFO
  4. # 打印执行的数据库以及语句
  5. spring.shardingsphere.props.sql.show=true
  6. # 数据源 ds0 ds1
  7. spring.shardingsphere.datasource.names=ds0,ds1
  8. # 第一个数据库
  9. spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
  10. spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
  11. spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://localhost:3306/ybe_shop_order0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
  12. spring.shardingsphere.datasource.ds0.username=root
  13. spring.shardingsphere.datasource.ds0.password=*****
  14. # 第二个数据库
  15. spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
  16. spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
  17. spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://localhost:3306/ybe_shop_order1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
  18. spring.shardingsphere.datasource.ds1.username=root
  19. spring.shardingsphere.datasource.ds1.password=*****

2.广播表介绍和配置实战

  1. 添加AdConfigDO实体类和添加ProductOrderDOMapper类
  1. //数据库实体类
  2. @Data
  3. @EqualsAndHashCode(callSuper = false)
  4. @TableName("ad_config")
  5. public class AdConfigDO {
  6. private Long id;
  7. private String configKey;
  8. private String configValue;
  9. private String type;
  10. }
  11. //数据库实体配置类
  12. public interface AdConfigMapper extends BaseMapper<AdConfigDO> {
  13. }
  1. 设置ad_config为广播表,如果需要配置多个用 逗号 (,) 分开;设置id为生成算法为雪花算法。配置文件中添加如下代码,
  1. #配置广播表
  2. spring.shardingsphere.sharding.broadcast-tables=ad_config
  3. spring.shardingsphere.sharding.tables.ad_config.key-generator.column=id
  4. spring.shardingsphere.sharding.tables.ad_config.key-generator.type=SNOWFLAKE
  1. 添加测试方法
  1. @Test
  2. public void testSaveAdConfig(){
  3. AdConfigDO adConfigDO = new AdConfigDO();
  4. adConfigDO.setConfigKey("banner");
  5. adConfigDO.setConfigValue("ybe.com");
  6. adConfigDO.setType("ad");
  7. adConfigMapper.insert(adConfigDO);
  8. }
  1. 执行结果,两个数据库的表都进行了更新。如下图

3.绑定表介绍和配置实战

  1. 添加ProductOrderItemDO实体类和添加ProductOrderDOMapper类
  1. //数据库实体类
  2. @Data
  3. @TableName("product_order_item")
  4. @EqualsAndHashCode(callSuper = false)
  5. public class ProductOrderItemDO {
  6. private Long id;
  7. private Long productOrderId;
  8. private Long productId;
  9. private String productName;
  10. private Integer buyNum;
  11. private Long userId;
  12. }
  13. //数据库实体配置类
  14. public interface ProductOrderItemMapper extends BaseMapper<ProductOrderItemDO> {
  15. }
  1. 添加配置文件,设置product_order和product_order_ite为广播表,如果需要配置多个需要配置多行,binding-tables是个数据
  1. #配置绑定表
  2. spring.shardingsphere.sharding.binding-tables[0]=product_order,product_order_item
  1. 添加测试方法
  1. @Test
  2. public void testBinding(){
  3. List<Object> objects = productOrderMapper.listProductOrderDetail();
  4. System.out.println(objects);
  5. }
  1. 执行结果:

    • 添加绑定表配置之前,可以看到查询的sql语句,主表和子表是笛卡尔积的关联关系。如下图,

    • 添加绑定表配置之后,可以看到查询的sql语句,主表和子表是一一对应的。如下图,

4.行表达式分片策略 InlineShardingStrategy

  • 只支持【单分片键】使用Groovy的表达式,提供对SQL语句中的 =和IN 的分片操作支持
  • 可以通过简单的配置使用,无需自定义分片算法,从而避免繁琐的Java代码开发
  1. 添加ProductOrderDO实体类和添加ProductOrderDOMapper类
  1. //数据库实体类
  2. @Data
  3. @TableName("product_order")
  4. @EqualsAndHashCode(callSuper = false)
  5. public class ProductOrderDO {
  6. // 不设置Mybatis-plus的主键规则,由sharding-jdbc 设置
  7. private Long id;
  8. private String outTradeNo;
  9. private String state;
  10. private Date createTime;
  11. private Double payAmount;
  12. private String nickname;
  13. private Long userId;
  14. }
  15. //数据库实体配置类
  16. public interface ProductOrderMapper extends BaseMapper<ProductOrderDO> {
  17. }
  1. 配置文件添加如下代码,
  1. # 指定product_order表的数据分布情况,配置数据节点,行表达式标识符使用 ${...} 或 $->{...},但前者与 Spring 本身的文件占位符冲突,所以在 Spring 环境中建议使用 $->{...}
  2. spring.shardingsphere.sharding.tables.product_order.actual-data-nodes=ds$->{0..1}.product_order_$->{0..1}
  3. #id生成策略
  4. spring.shardingsphere.sharding.tables.product_order.key-generator.column=id
  5. spring.shardingsphere.sharding.tables.product_order.key-generator.type=SNOWFLAKE
  6. #work_id 的设置
  7. spring.shardingsphere.sharding.tables.product_order.key-generator.props.worker.id=1
  8. #配置分库规则
  9. spring.shardingsphere.sharding.tables.product_order.database-strategy.inline.sharding-column=user_id
  10. spring.shardingsphere.sharding.tables.product_order.database-strategy.inline.algorithm-expression=ds$->{user_id % 2}
  11. #配置分表规则
  12. #指定product_order表的分片策略,分片策略包括【分片键和分片算法】
  13. spring.shardingsphere.sharding.tables.product_order.table-strategy.inline.sharding-column=id
  14. spring.shardingsphere.sharding.tables.product_order.table-strategy.inline.algorithm-expression=product_order_$->{id % 2}

由配置文件可知,

​ 设置了product_order为逻辑表,设置了它的真实数据节点为ds$->{0..1}.product_order_$->{0..1},使用了表达式$->{...},它表示实际的物理表为:ds0.product_order_0,ds0.product_order_1,ds1.product_order_0,ds1.product_order_1,总共对应了2个库的2个物理表。

​ 设置了product_order表的id计算方式为雪花算法;

​ 设置了product_order表的分库规则,分库规则为 user_id % 2;也就是说会根据user_id % 2的结果确定是ds0库还是ds1库。

​ 设置了product_order表的分表规则,分表规则为 id % 2;也就是说会根据id % 2的结果确定是product_order_0表还是product_order_1表。

  1. 添加测试方法
  1. @Test
  2. public void testSaveProductOrder(){
  3. Random random = new Random();
  4. for (int i = 0 ;i < 10 ; i++){
  5. // id是由配置的雪花算法生成
  6. ProductOrderDO productOrderDO = new ProductOrderDO();
  7. productOrderDO.setCreateTime(new Date());
  8. productOrderDO.setNickname("ybe:"+i);
  9. productOrderDO.setOutTradeNo(UUID.randomUUID().toString().substring(0,32));
  10. productOrderDO.setPayAmount(100.00);
  11. productOrderDO.setState("PAY");
  12. // 随机生成UserId
  13. productOrderDO.setUserId(Long.valueOf(random.nextInt(50)));
  14. productOrderMapper.insert(productOrderDO);
  15. }
  16. }
  1. 执行结果根据不同的user_id 和 id ,生成的表记录插入到了不同的库和表,如下图可以看到数据分散在了两个不同的数据库,以及不同的表中。

5.标准分片策略StandardShardingStrategy

  • 只支持【单分片键】,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法
  • PreciseShardingAlgorithm 精准分片 是必选的,用于处理=和IN的分片
  • RangeShardingAlgorithm 范围分片 是可选的,用于处理BETWEEN AND分片
  • 如果不配置RangeShardingAlgorithm,如果SQL中用了BETWEEN AND语法,则将按照全库路由处理,性能下降
  1. 添加分表配置类CustomTablePreciseShardingAlgorithm
  1. public class CustomTablePreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
  2. /**
  3. * @param collection 数据源集合
  4. * 在分库时值为所有分片库的集合 databaseNames
  5. * 分表时为对应分片库中所有分片表的集合 tablesNames
  6. * @param preciseShardingValue 分片属性,包括
  7. * logicTableName 为逻辑表,
  8. * columnName 分片健(字段),
  9. * value 为从 SQL 中解析出的分片健的值
  10. * @return
  11. */
  12. @Override
  13. public String doSharding(Collection<String> collection, PreciseShardingValue<Long> preciseShardingValue) {
  14. //循环遍历 数据源,根据算法
  15. for (String databaseName : collection) {
  16. String value = preciseShardingValue.getValue() % collection.size() + "";
  17. //value是0,则进入0库表,1则进入1库表
  18. if (databaseName.endsWith(value)) {
  19. return databaseName;
  20. }
  21. }
  22. throw new IllegalArgumentException();
  23. }
  24. }
  1. 添加分库配置类CustomDBPreciseShardingAlgorithm
  1. /**
  2. * @param collection 数据源集合
  3. * 在分库时值为所有分片库的集合 databaseNames
  4. * 分表时为对应分片库中所有分片表的集合 tablesNames
  5. * @param preciseShardingValue 分片属性,包括
  6. * logicTableName 为逻辑表,
  7. * columnName 分片健(字段),
  8. * value 为从 SQL 中解析出的分片健的值
  9. * @return
  10. */
  11. @Override
  12. public String doSharding(Collection<String> collection, PreciseShardingValue<Long> preciseShardingValue) {
  13. for (String databaseName : collection) {
  14. String value = preciseShardingValue.getValue() % collection.size() + "";
  15. //value是0,则进入0库表,1则进入1库表
  16. if (databaseName.endsWith(value)) {
  17. return databaseName;
  18. }
  19. }
  20. throw new IllegalArgumentException();
  21. }
  1. 添加分表范围配置类CustomRangeShardingAlgorithm
  1. public class CustomRangeShardingAlgorithm implements RangeShardingAlgorithm<Long> {
  2. /**
  3. * @param collection 数据源集合
  4. * 在分库时值为所有分片库的集合 databaseNames
  5. * 分表时为对应分片库中所有分片表的集合 tablesNames
  6. * @param rangeShardingValue 分片属性,包括
  7. * logicTableName 为逻辑表,
  8. * columnName 分片健(字段),
  9. * value 为从 SQL 中解析出的分片健的值
  10. * @return
  11. */
  12. @Override
  13. public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Long> rangeShardingValue) {
  14. Set<String> result = new LinkedHashSet<>();
  15. // between 起始值
  16. Long lower = rangeShardingValue.getValueRange().lowerEndpoint();
  17. // between 结束值
  18. Long upper = rangeShardingValue.getValueRange().upperEndpoint();
  19. // 循环范围计算分库逻辑
  20. for (long i = lower; i <= upper; i++) {
  21. for (String databaseName : collection) {
  22. if (databaseName.endsWith(i % collection.size() + "")) {
  23. result.add(databaseName);
  24. }
  25. }
  26. }
  27. return result;
  28. }
  29. }
  1. 配置文件添加图下代码,
  1. # 分库分片算法
  2. spring.shardingsphere.sharding.tables.product_order.database-strategy.standard.sharding-column=user_id
  3. spring.shardingsphere.sharding.tables.product_order.database-strategy.standard.precise-algorithm-class-name=com.ybe.algorithm.CustomDBPreciseShardingAlgorithm
  4. #精准水平分表下,增加一个范围分片
  5. spring.shardingsphere.sharding.tables.product_order.table-strategy.standard.range-algorithm-class-name=com.ybe.algorithm.CustomRangeShardingAlgorithm
  6. # 分表分片健
  7. spring.shardingsphere.sharding.tables.product_order.table-strategy.standard.sharding-column=id
  8. spring.shardingsphere.sharding.tables.product_order.table-strategy.standard.precise-algorithm-class-name=com.ybe.algorithm.CustomTablePreciseShardingAlgorithm
  1. 添加测试方法
  1. @Test
  2. public void testRand(){
  3. Random random = new Random();
  4. for (int i = 0 ;i < 10 ; i++){
  5. ProductOrderDO productOrderDO = new ProductOrderDO();
  6. productOrderDO.setCreateTime(new Date());
  7. productOrderDO.setNickname("ybe:"+i);
  8. productOrderDO.setOutTradeNo(UUID.randomUUID().toString().substring(0,32));
  9. productOrderDO.setPayAmount(100.00);
  10. productOrderDO.setState("PAY");
  11. productOrderDO.setUserId(Long.valueOf(random.nextInt(50)));
  12. productOrderMapper.insert(productOrderDO);
  13. }
  14. productOrderMapper.selectList(new QueryWrapper<ProductOrderDO>().between("id",1L,1L));
  15. }
  1. 执行结果:1.会根据配置的分库、分表规则进行插入不同的数据库和表;2.范围(between)查询的时候会根据id的范围值查询映射的物理表集合。

6.标准分片策略StandardShardingStrategy

  • 只支持【单分片键】,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法
  • PreciseShardingAlgorithm 精准分片 是必选的,用于处理=和IN的分片
  • RangeShardingAlgorithm 范围分片 是可选的,用于处理BETWEEN AND分片
  • 如果不配置RangeShardingAlgorithm,如果SQL中用了BETWEEN AND语法,则将按照全库路由处理,性能下降

添加分表配置类CustomTablePreciseShardingAlgorithm

  1. public class CustomTablePreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
  2. /**
  3. * @param collection 数据源集合
  4. * 在分库时值为所有分片库的集合 databaseNames
  5. * 分表时为对应分片库中所有分片表的集合 tablesNames
  6. * @param preciseShardingValue 分片属性,包括
  7. * logicTableName 为逻辑表,
  8. * columnName 分片健(字段),
  9. * value 为从 SQL 中解析出的分片健的值
  10. * @return
  11. */
  12. @Override
  13. public String doSharding(Collection<String> collection, PreciseShardingValue<Long> preciseShardingValue) {
  14. //循环遍历 数据源,根据算法
  15. for (String databaseName : collection) {
  16. String value = preciseShardingValue.getValue() % collection.size() + "";
  17. //value是0,则进入0库表,1则进入1库表
  18. if (databaseName.endsWith(value)) {
  19. return databaseName;
  20. }
  21. }
  22. throw new IllegalArgumentException();
  23. }
  24. }

添加分库配置类CustomDBPreciseShardingAlgorithm

  1. /**
  2. * @param collection 数据源集合
  3. * 在分库时值为所有分片库的集合 databaseNames
  4. * 分表时为对应分片库中所有分片表的集合 tablesNames
  5. * @param preciseShardingValue 分片属性,包括
  6. * logicTableName 为逻辑表,
  7. * columnName 分片健(字段),
  8. * value 为从 SQL 中解析出的分片健的值
  9. * @return
  10. */
  11. @Override
  12. public String doSharding(Collection<String> collection, PreciseShardingValue<Long> preciseShardingValue) {
  13. for (String databaseName : collection) {
  14. String value = preciseShardingValue.getValue() % collection.size() + "";
  15. //value是0,则进入0库表,1则进入1库表
  16. if (databaseName.endsWith(value)) {
  17. return databaseName;
  18. }
  19. }
  20. throw new IllegalArgumentException();
  21. }

添加分表范围配置类CustomRangeShardingAlgorithm

  1. public class CustomRangeShardingAlgorithm implements RangeShardingAlgorithm<Long> {
  2. /**
  3. * @param collection 数据源集合
  4. * 在分库时值为所有分片库的集合 databaseNames
  5. * 分表时为对应分片库中所有分片表的集合 tablesNames
  6. * @param rangeShardingValue 分片属性,包括
  7. * logicTableName 为逻辑表,
  8. * columnName 分片健(字段),
  9. * value 为从 SQL 中解析出的分片健的值
  10. * @return
  11. */
  12. @Override
  13. public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Long> rangeShardingValue) {
  14. Set<String> result = new LinkedHashSet<>();
  15. // between 起始值
  16. Long lower = rangeShardingValue.getValueRange().lowerEndpoint();
  17. // between 结束值
  18. Long upper = rangeShardingValue.getValueRange().upperEndpoint();
  19. // 循环范围计算分库逻辑
  20. for (long i = lower; i <= upper; i++) {
  21. for (String databaseName : collection) {
  22. if (databaseName.endsWith(i % collection.size() + "")) {
  23. result.add(databaseName);
  24. }
  25. }
  26. }
  27. return result;
  28. }
  29. }

添加配置文件

  1. # 分库分片算法
  2. spring.shardingsphere.sharding.tables.product_order.database-strategy.standard.sharding-column=user_id
  3. spring.shardingsphere.sharding.tables.product_order.database-strategy.standard.precise-algorithm-class-name=com.ybe.algorithm.CustomDBPreciseShardingAlgorithm
  4. #精准水平分表下,增加一个范围分片
  5. spring.shardingsphere.sharding.tables.product_order.table-strategy.standard.range-algorithm-class-name=com.ybe.algorithm.CustomRangeShardingAlgorithm
  6. # 分表分片健
  7. spring.shardingsphere.sharding.tables.product_order.table-strategy.standard.sharding-column=id
  8. spring.shardingsphere.sharding.tables.product_order.table-strategy.standard.precise-algorithm-class-name=com.ybe.algorithm.CustomTablePreciseShardingAlgorithm

添加测试方法

  1. @Test
  2. public void testRand(){
  3. Random random = new Random();
  4. for (int i = 0 ;i < 10 ; i++){
  5. ProductOrderDO productOrderDO = new ProductOrderDO();
  6. productOrderDO.setCreateTime(new Date());
  7. productOrderDO.setNickname("ybe:"+i);
  8. productOrderDO.setOutTradeNo(UUID.randomUUID().toString().substring(0,32));
  9. productOrderDO.setPayAmount(100.00);
  10. productOrderDO.setState("PAY");
  11. productOrderDO.setUserId(Long.valueOf(random.nextInt(50)));
  12. productOrderMapper.insert(productOrderDO);
  13. }
  14. productOrderMapper.selectList(new QueryWrapper<ProductOrderDO>().between("id",1L,1L));
  15. }

执行结果:1.会根据配置的分库、分表规则进行插入不同的数据库和表;2.between范围查询的时候会根据id查询映射的物理表集合。

7.复合分片算法ComplexShardingStrategy

  • 提供对SQL语句中的=, IN和BETWEEN AND的分片操作,支持【多分片键】
  • 由于多分片键之间的关系复杂,Sharding-JDBC并未做过多的封装
  • 而是直接将分片键值组合以及分片操作符交于算法接口,全部由应用开发者实现,提供最大的灵活度
  1. 添加分表配置类CustomComplexKeysShardingAlgorithm
  1. public class CustomComplexKeysShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
  2. @Override
  3. public Collection<String> doSharding(Collection<String> collection, ComplexKeysShardingValue<Long> complexKeysShardingValue) {
  4. // 得到每个分片健对应的值
  5. Collection<Long> orderIdValues = this.getShardingValue(complexKeysShardingValue, "id");
  6. Collection<Long> userIdValues = this.getShardingValue(complexKeysShardingValue, "user_id");
  7. List<String> shardingSuffix = new ArrayList<>();
  8. // 对两个分片健取模的方式
  9. for (Long userId : userIdValues) {
  10. for (Long orderId : orderIdValues) {
  11. String suffix = userId % 2 + "_" + orderId % 2;
  12. for (String databaseName : collection) {
  13. if (databaseName.endsWith(suffix)) {
  14. shardingSuffix.add(databaseName);
  15. }
  16. }
  17. }
  18. }
  19. return shardingSuffix;
  20. }
  21. /**
  22. * shardingValue 分片属性,包括
  23. * logicTableName 为逻辑表,
  24. * columnNameAndShardingValuesMap 存储多个分片健 包括key-value
  25. * key:分片key,id和user_id
  26. * value:分片value,66和99
  27. *
  28. * @return shardingValues 集合
  29. */
  30. private Collection<Long> getShardingValue(ComplexKeysShardingValue<Long> shardingValues, final String key) {
  31. Collection<Long> valueSet = new ArrayList<>();
  32. Map<String, Collection<Long>> columnNameAndShardingValuesMap = shardingValues.getColumnNameAndShardingValuesMap();
  33. if (columnNameAndShardingValuesMap.containsKey(key)) {
  34. valueSet.addAll(columnNameAndShardingValuesMap.get(key));
  35. }
  36. return valueSet;
  37. }
  1. 配置文件添加如下代码,多个列的类型必须一样。
  1. # 复合分片算法,order_id,user_id 同时作为分片健
  2. spring.shardingsphere.sharding.tables.product_order.table-strategy.complex.sharding-columns=user_id,id
  3. spring.shardingsphere.sharding.tables.product_order.table-strategy.complex.algorithm-class-name=com.ybe.algorithm.CustomComplexKeysShardingAlgorithm
  1. 添加测试方法
  1. @Test
  2. public void testComplex(){
  3. productOrderMapper.selectList(new QueryWrapper<ProductOrderDO>().eq("id",66L).eq("user_id",99L));
  4. }
  1. 执行结果:1.会根据配置的复合分片算法去查找相关的物理表。

8.Hint分片算法HintShardingStrategy

  • 这种分片策略无需配置文件进行配置分片健,分片健值也不再从 SQL中解析,外部手动指定分片健或分片库,让 SQL在指定的分库、分表中执行
  • 通过Hint代码指定的方式而非SQL解析的方式分片的策略
  • Hint策略会绕过SQL解析的,对于这些比较复杂的需要分片的查询,Hint分片策略性能可能会更好
  • 可以指定sql去某个库某个表进行执行
  1. 添加分表配置类CustomTableHintShardingAlgorithm
  1. public class CustomTableHintShardingAlgorithm implements HintShardingAlgorithm<Long> {
  2. @Override
  3. public Collection<String> doSharding(Collection<String> collection, HintShardingValue<Long> hintShardingValue) {
  4. Collection<String> result = new ArrayList<>();
  5. for (String tableName : collection) {
  6. for (Long shardingValue : hintShardingValue.getValues()) {
  7. if (tableName.endsWith(String.valueOf(shardingValue % collection.size()))) {
  8. result.add(tableName);
  9. }
  10. }
  11. }
  12. return result;
  13. }
  14. }
  1. 添加分库配置类CustomDBHintShardingAlgorithm
  1. public class CustomDBHintShardingAlgorithm implements HintShardingAlgorithm<Long>
  2. {
  3. @Override
  4. public Collection<String> doSharding(Collection<String> collection, HintShardingValue<Long> hintShardingValue) {
  5. Collection<String> result = new ArrayList<>();
  6. for (String dbName : collection) {
  7. for (Long shardingValue : hintShardingValue.getValues()) {
  8. if (dbName.endsWith(String.valueOf(shardingValue % collection.size()))) {
  9. result.add(dbName);
  10. }
  11. }
  12. }
  13. return result;
  14. }
  15. }
  1. 配置文件添加如下代码
  1. # Hint分片算法
  2. spring.shardingsphere.sharding.tables.product_order.table-strategy.hint.algorithm-class-name=com.ybe.algorithm.CustomTableHintShardingAlgorithm
  3. spring.shardingsphere.sharding.tables.product_order.database-strategy.hint.algorithm-class-name=com.ybe.algorithm.CustomDBHintShardingAlgorithm
  1. 添加测试方法
  1. @Test
  2. public void testHint(){
  3. // 清除掉历史的规则
  4. HintManager.clear();
  5. //Hint分片策略必须要使用 HintManager工具类
  6. HintManager hintManager = HintManager.getInstance();
  7. // 设置库的分片健,value用于库分片取模,
  8. hintManager.addDatabaseShardingValue("product_order",4L);
  9. // 设置表的分片健,value用于表分片取模,
  10. hintManager.addTableShardingValue("product_order", 5L);
  11. //对应的value只做查询,不做sql解析
  12. productOrderMapper.selectList(new QueryWrapper<ProductOrderDO>().eq("id", 66L));
  13. }
  1. 执行结果:1.不会解析Sql中的分片键,会把hintManager配置的值作为分片键,在CustomTableHintShardingAlgorithm分片算法的中使用。

ShardingSphere-JDBC实战的更多相关文章

  1. JDBC实战案例--利用jdbc实现的宠物信息管理系统

    一.需求: 利用jdbc实现对宠物的信息进行管理的一套系统 宠物信息:宠物ID,宠物类别,宠物名字,宠物性别,宠物年龄,宠物入库日期 系统完成功能:实现对宠物信息的录入,修改,删除,查询. 二.解决方 ...

  2. spark之JDBC开发(实战)

    一.概述 Spark Core.Spark-SQL与Spark-Streaming都是相同的,编写好之后打成jar包使用spark-submit命令提交到集群运行应用$SPARK_HOME/bin#. ...

  3. 重磅|Apache ShardingSphere 5.0.0 即将正式发布

    Apache ShardingSphere 5.0.0 GA 版在经历 5.0.0-alpha 及 5.0.0-beta 接近两年时间的研发和打磨,终于将在 11 月份与大家正式见面! 11 月 10 ...

  4. JDBC上

    JDBC实战--打通数据库 代码实现: package com.imooc.db; import java.sql.Connection; import java.sql.DriverManager; ...

  5. Apache ShardingSphere 5.1.2 发布|全新驱动 API + 云原生部署,打造高性能数据网关

    在 Apache ShardingSphere 5.1.1 发布后,ShardingSphere 合并了来自全球的团队或个人的累计 1028 个 PR,为大家带来 5.1.2 新版本.该版本在功能.性 ...

  6. MYSQL的Java操作器——JDBC

    MYSQL的Java操作器--JDBC 在学习了Mysql之后,我们就要把Mysql和我们之前所学习的Java所结合起来 而JDBC就是这样一种工具:帮助我们使用Java语言来操作Mysql数据库 J ...

  7. Hibernate学习笔记整理系列-------一、Hibernate简介

    Hibernate的官网:http://hibernate.org/ 1.1 Hibernate框架的作用 Hibernate框架是一个数据访问框架(也叫持久层框架,可将实体对象变成持久对象).通过H ...

  8. SpringCloud微服务实战——搭建企业级开发框架(二十七):集成多数据源+Seata分布式事务+读写分离+分库分表

    读写分离:为了确保数据库产品的稳定性,很多数据库拥有双机热备功能.也就是,第一台数据库服务器,是对外提供增删改业务的生产服务器:第二台数据库服务器,主要进行读的操作. 目前有多种方式实现读写分离,一种 ...

  9. ShardingSphere 集成 CosId 实战

    背景 在软件系统演进过程中,随着业务规模的增长 (TPS/存储容量),我们需要通过集群化部署来分摊计算.存储压力. 应用服务的无状态设计使其具备了伸缩性.在使用 Kubernetes 部署时我们只需要 ...

  10. 综合实战--文件上传系统【JDBC&IO&Socket】

    本文纯属记录第一次实战遇到的坑和知识,如果后边有时间再做整理. 1,先写了个操作数据库的工具类SqlTool,照着JDBC资料打完之后,测试的时候出错了,java.lang.ClassNotFound ...

随机推荐

  1. 动态调试JS脚本文件:(JS源映射 - sourceURL)与 debugger

    我们在进行js调试时经常会对js进行调试,chrome 对js提示对支持非常友好,只需要F12就可以打开chrome的调试器 在sources里面就是页面请求后加载的一些资源文件,我们可以找到我们的j ...

  2. MySQL的Explain总结

    Explain简介 MySQL优化器在基于成本的计算和基于规则的SQL优化会生成一个所谓的执行计划,我们就可以使用执行计划查看MySQL对该语句具体的执行方式. 介绍这个好啰嗦就是了,我们可以通过这个 ...

  3. 用树莓派USB摄像头做个监控

    [前言] 看着阴暗的角落里吃灰噎到嗓子眼的树莓派,一起陪伴的时光历历在目,往事逐渐涌上心头,每每触及此处,内心总会升腾起阵阵怜悯之情... 我这有两个设备,一个是积灰已久的树莓派,另一个是积灰已久的U ...

  4. Mac Book安装Windows发烫的问题

    Mac Book安装Windows后,电脑发烫,风扇一直高速旋转.针对此问题百度搜索了一下, 大多数人说更改电源选项,由"平衡"模式改为"节能"模式,亲身体验了 ...

  5. WindowsServer评估版转为正式版并激活

    更新记录 本文迁移自Panda666原博客,原发布时间:2021年5月16日. 一般从官网下载的Windows Server版本都是评估试用版本.这时候想转为正式版本,就需要使用转换激活代码.请参照不 ...

  6. 【2022-06-16】Pycharm的下载与安装使用

    一.Pycharm软件简介 产品简介 PyCharm是一种Python IDE(Integrated Development Environment,集成开发环境),带有一整套可以帮助用户在使用Pyt ...

  7. 从0到1搭建一款Vue可配置视频播放器组件(Npm已发布)

    前言 话不多说,这篇文章主要讲述如何从0到1搭建一款适用于Vue.js的自定义配置视频播放器.我们平时在PC端网站上观看视频时,会看到有很多丰富样式的视频播放器,而我们自己写的video标签样式却是那 ...

  8. 深入理解 volatile 关键字

    volatile 关键字是 Java 语言的高级特性,但要弄清楚其工作原理,需要先弄懂 Java 内存模型.如果你之前没了解过 Java 内存模型,那可以先看看之前我写过的一篇「深入理解 Java 内 ...

  9. 使用net core 6 c# 的 NPOI 包,读取excel..xlsx单元格内的图片,并存储到指定服务器

    这个是记录,单元格的图片. 直接上代码,直接新建一个 net core api 解决方案,引用一下nuget包.本地创建一个 .xlsx 格式的excel文件 using ICSharpCode.Sh ...

  10. Springboot 整合 MongoDB

    Springboot 整合 MongoDB 这节我们将整合 Spring Boot 与 Mongo DB 实现增删改查的功能,并且实现序列递增. Mongo DB 的基本介绍和增删改查的用法可以参考我 ...