Spring Boot 与 Sharding JDBC 的分库分表集成配置

一. Sharding JDBC介绍

Sharding-Sphere的前身Sharding-JDBC是由当当的应用框架dd-frame中的dd-rdb模块演进而来, 是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar这3款相互独立的产品组成。
Sharding-JDBC 可适用于任何基于Java的ORM框架,如JPA、Hibernate、MyBatis、Spring JDBC Template等, 支持第三方的数据库连接池,如DBCP、C3P0、BoneCP、Druid等。
在这里插入图片描述

二. Sharding JDBC的使用限制

Sharding JDBC, Mycat, Drds 等产品都是分布式数据库中间件, 相比直接的数据源操作, 会存在一些限制, Sharding JDBC在使用时, 要注意以下问题:

  • 有限支持子查询
  • 不支持HAVING
  • 不支持OR,UNION 和 UNION ALL
  • 不支持特殊INSERT
  • 每条INSERT语句只能插入一条数据,不支持VALUES后有多行数据的语句
  • 不支持DISTINCT聚合
  • 不支持dual虚拟表查询
  • 不支持SELECT LAST_INSERT_ID(), 不支持自增序列
  • 不支持CASE WHEN

三. Sharding JDBC的集成配置

  1. POM依赖

    <!-- sharding-jdbc 依赖 -->
    <dependency>
        <groupId>io.shardingsphere</groupId>
        <artifactId>sharding-jdbc-core</artifactId>
        <version>3.1.0</version>
    </dependency>
    
  2. 实现分库分片配置:
    假设数据库表结构:
    订单表(t_order)字段: 订单ID(orderId), 年份(year)
    分库规则为: 根据年份分库, 比如2019, 对应的数据库为DB_2019; 年份2020, 对应的库为DB_2020.
    分表规则为: 根据订单ID取模, 散落分配在3个表中.
    具体实现:

    • 定义分库规则

      public class DBSplitRule implements PreciseShardingAlgorithm<String> {
          /**
           * 分库规则设置
           * @param collection
           * @param preciseShardingValue
           * @return
           */
          @Override
          public String doSharding(Collection<String> collection, PreciseShardingValue<String> preciseShardingValue) {
              // 取出属性值
              String year = preciseShardingValue.getValue();
              // 根据属性值判断处理
              if("2019".equals(year)) {
                  return "DB_2019";
              }else if("2020".equals(year)){
                  return "DB_2020";
              }
              return "DB_2020";
          }
      }
      
      
    • 定义分片规则

      @Log4j2
      public class TableSplitRule implements PreciseShardingAlgorithm<Integer> {
      
      
         /**
           * 制定分片规则
           */
          @Override
          public String doSharding(Collection<String> collection, PreciseShardingValue<Long> preciseShardingValue) {
              log.info("Process in TableSplitRule .doSharding method, collection: " + collection + ", collection: " + preciseShardingValue);
              String tableName = preciseShardingValue.getLogicTableName() + "_";
              try {
                  // 获取类型值
                  Long orderId = preciseShardingValue.getValue();
                  long mod = Math.floorMod(orderId, 3l);
                  if(mod == 1) {
                      // 第一个表
                      tableName = tableName + "_1";
                  }else if(mod == 2) {
                      // 第二个表
                      tableName = tableName + "_2";
                  }else if(mod == 3) {
                      // 第三个表
                      tableName = tableName + "_3";
                  }else {
                      throw new Exception("Not Match Table, result: " + mod);
                  }
                  log.info("result table name:" + tableName);
                  return tableName;
              } catch (Exception e) {
                  log.error(e.getMessage(), e);
                  throw new RuntimeException(e.getMessage());
              }
      
          }
      
      }
      
      
    • Sharding Jdbc 数据源配置
      这里是基于Druid连接池实现的集成配置.

      @Configuration
      public class DruidDataSourceConfiguration {
      	/**
           * 分表配置规则
           */
          private TableRuleConfiguration getSplitOrderTableRule() {
              TableRuleConfiguration result = new TableRuleConfiguration();
              // 指定需要通过sharding-jdbc路由的表
              result.setLogicTable("t_order");		
              //  分库配置, 代表数据库根据年份分了两个库,  表t_order分了1至3共3个表
              result.setActualDataNodes("DB_${2019..2020}.t_order_${1..3}");		
              // 分库规则配置
              result.setDatabaseShardingStrategyConfig(new StandardShardingStrategyConfiguration("year", new DBSplitRule ()));
              result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("orderId", new TableSplitRule ()));
              return result;
          }
      	
      	/**
           * 数据源配置
           * @return
           */
          @Bean(name = "shardingDataSource")
          public DataSource shardingDataSource(@Autowired  DruidDataSource druidDataSource) throws Exception{
      
              ShardingRuleConfiguration shardJdbcConfig = new ShardingRuleConfiguration();
              shardJdbcConfig.getTableRuleConfigs().add(getSplitOrderTableRule());
              shardJdbcConfig.setDefaultDataSourceName("DB_2020");
              Map<String,DataSource> dataMap = new LinkedHashMap<>() ;
              // 多个分库配置对应的数据源配置
              dataMap.put("DB_2019",druidDataSource) ;
              dataMap.put("DB_2020",druidDataSource) ;	
              Properties prop = new Properties();
              prop.put("sql.show", true);
              return ShardingDataSourceFactory.createDataSource(dataMap, shardJdbcConfig, new HashMap<>(), prop);
      
          }
      }
      
      

      这里实现了订单的分表, 通过getSplitOrderTableRule方法配置了订单表的分表规则, 如果还需要对其他表做分表处理, 可以参照getSplitOrderTableRule新增方法追加规则配置.

  3. 全局序列ID配置及注意的问题
    前面讲过, Sharding JDBC 不支持自增序列,
    如果通过JPA对数据层进行操作, 需要去除@GeneratedValue(strategy = GenerationType.IDENTITY)
    如果数据库是Postgresql, 数据库属性是采用小写, 我们要加上映射@Column(name=“orderid”), 否则SQL处理的时候会报错:

    java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.rangeCheck(ArrayList.java:657)
    at java.util.ArrayList.get(ArrayList.java:433)
    at io.shardingsphere.core.executor.sql.execute.result.MemoryQueryResult.getColumnIndex(MemoryQueryResult.java:151)
    

本文由mirson创作分享,如需进一步交流,请加QQ群:19310171或访问www.softart.cn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

麦神-mirson

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值