sharding-sphere 單庫分表實例


 

生成表SQL,多張表日期累加

fund_record20208

fund_record20209

fund_record20210

 
-- ----------------------------
-- Table structure for fund_record20208
-- ----------------------------
DROP TABLE IF EXISTS `fund_record20208`;
CREATE TABLE `fund_record20208`  (
  `id` bigint(64) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '用戶ID',
  `amount` decimal(20, 8) NULL DEFAULT NULL COMMENT '流水金額',
  `amount_fee` decimal(20, 8) NULL DEFAULT NULL COMMENT '手續費',
  `operate` int(11) NULL DEFAULT NULL COMMENT '1用戶充值,2 商城消費, 3轉賬支出 ',
  `order_no` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '訂單編號',
  `reason` varchar(500) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '原因(充值or商品名稱)',
  `create_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '創建用戶',
  `create_date` datetime(0) NULL DEFAULT NULL COMMENT '創建時間',
  `type` tinyint(1) NULL DEFAULT NULL COMMENT '貨幣類型:1 RMB 2 沃金(WG) 3 元寶(DT) ',
  `symbol` varchar(2) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '收入支出符號: + (加號)  - (減號)',
  `after_balance` decimal(20, 8) NULL DEFAULT NULL COMMENT '變動后余額',
  `old_id` int(11) NULL DEFAULT NULL COMMENT '原流水Id',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1304357960402001923 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

 

yaml 配置文件

spring:


  shardingsphere:
    props:
      sql:
        #設置sql是否展示
        show: true
        check:
          table:
            metadata:
              enabled: true
    datasource:
      #數據庫名稱(可以與數據庫中的庫名不一致)
      names: master
      master:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://wqspro.tpddns.cn:13306/yuan_mall?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&tinyInt1isBit=false
        username: root
        password: cYyq8wtbuBO$XnpF
        # 數據庫連接池的最小連接數
        initial-size: 10
        max-active: 100
        min-idle: 10
        max-wait: 60000
        pool-prepared-statements: true
        max-pool-prepared-statement-per-connection-size: 20
        time-between-eviction-runs-millis: 60000
        min-evictable-idle-time-millis: 300000
        validation-query: SELECT 1 FROM DUAL
        test-while-idle: true
        test-on-borrow: false
        test-on-return: false
        stat-view-servlet:
          enabled: true
          url-pattern: /druid/*
          #login-username: admin
          #login-password: admin
        filter:
          stat:
            log-slow-sql: true
            slow-sql-millis: 1000
            merge-sql: true
          wall:
            config:
              multi-statement-allow: true
    sharding:
      #分庫策略
      #      default-database-strategy:
      #        inline:
      #          #根據id取模決定去那個庫
      #          algorithm-expression: ds$->{id % 2}
      #          sharding-column: id
      tables:
        #邏輯表名,fund_record,fund_record20209,fund_record202010,fund_record202011為實際表
        fund_record:
          actual-data-nodes: master.fund_record2020$->{8..12} #master.fund_record2019$->{11..12},
          table-strategy:
            #根據id取模決定去那個表
            #            inline:
            #              sharding-column: id
            #              algorithm-expression: user_info_$->{id % 3}
            #algorithm-expression: fund_record_2019$->{id % 3}
            standard:
              shardingColumn: create_date
              precise-algorithm-class-name: com.jk.mall.api.config.MyPreciseShardingAlgorithm #精確分片算法類名稱,用於=和IN。。該類需實現PreciseShardingAlgorithm接口並提供無參數的構造器
              range-algorithm-class-name: com.jk.mall.api.config.MyRangeShardingAlgorithm #范圍分片算法類名稱,用於BETWEEN,可選。。該類需實現RangeShardingAlgorithm接口並提供無參數的構造器

          key-generator:
            #id使用雪花算法
            column: id
            #雪花算法
            type: SNOWFLAKE

 

自定義分片查詢算法 “=”和“in”的查詢

public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Date> {

    /**
     * "="與"IN"進行分片的場景
     * @param collection
     * @param preciseShardingValue
     * @return
     */
    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<Date> preciseShardingValue) {
        //對於庫的分片collection存放的是所有的庫的列表,這里代表flow_01~flow_12
        //配置的分片的sharding-column對應的值
        Date timeValue = preciseShardingValue.getValue();
        //分庫時配置的sharding-column
        String columnName = preciseShardingValue.getColumnName();
        //需要分庫的邏輯表
        String table = preciseShardingValue.getLogicTableName();
        if(StringUtils.isEmpty(timeValue)){
            throw new UnsupportedOperationException("preciseShardingValue is null");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyM");
        //按月路由
        for (String each : collection) {
            //獲取到月份
            String date  =  sdf.format(timeValue);
            if(each.endsWith(date)){
                //這里返回回去的就是最終需要查詢的表名
                return each;
            }
        }
        return "";
    }

 

#范圍分片算法類名稱,用於BETWEEN,"<,>"  需要注意的是 實現 RangeShardingAlgorithm接口的類型一定要與數據中表的 列名 數據類型一致
public class MyRangeShardingAlgorithm implements RangeShardingAlgorithm<Date> {
    /**
     * BETWEEN AND進行分片的場景
     *
     * @param collection
     * @param rangeShardingValue
     * @return
     */

    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Date> rangeShardingValue) {

        Range<Date> valueRange = rangeShardingValue.getValueRange();
        String strDateFormat = "yyyyM";
        String yyyy = "yyyy";
        String mm = "M";

        SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
        SimpleDateFormat yyyySdf = new SimpleDateFormat(yyyy);
        SimpleDateFormat mmSdf = new SimpleDateFormat(mm);

        Date startTime = valueRange.lowerEndpoint();
        Date endTime = valueRange.upperEndpoint();

        List<String> month = new ArrayList<>();
        if (yyyySdf.format(startTime).equals(yyyySdf.format(endTime))) {
            //年 相等
            if (mmSdf.format(startTime).equals(mmSdf.format(endTime))) {
                //月 相等 則不需要做任何處理
                month.add(sdf.format(endTime));

            } else {
                // 月 不相等 則將開始時間月份累加到結束時間的月份
                Calendar forcalendar = Calendar.getInstance();
                forcalendar.setTime(startTime);

                month.add(sdf.format(forcalendar.getTime()));
                for (int i = 0; i < 12; i++) {
                    forcalendar.add(Calendar.MONTH, 1);
                    if (mmSdf.format(forcalendar.getTime()).equals(mmSdf.format(endTime))) {

                        break;
                    }
                    month.add(sdf.format(forcalendar.getTime()));
                }
            }
        } else {
            //年 不相等 將開始時間的月累加 直到與結束時間相等
            Calendar yearCalendar = Calendar.getInstance();
            yearCalendar.setTime(startTime);

            month.add(sdf.format(startTime));
            for (int i = 0; i < 12; i++) {
                yearCalendar.add(Calendar.MONTH, 1);
                if (sdf.format(yearCalendar.getTime()).equals(sdf.format(endTime))) {
                    break;
                }

                month.add(sdf.format(yearCalendar.getTime()));
            }
        }


        month.add(sdf.format(endTime));


        // 如果有固定范圍則取
//        if (valueRange.hasLowerBound()) {
//            Date lowerEndpoint = valueRange.lowerEndpoint();
//            leftDate = sdf.format(lowerEndpoint);
//
//        }
//        if (valueRange.hasUpperBound()) {
//            Date upperEndpoint = valueRange.upperEndpoint();
//            rightDate = sdf.format(upperEndpoint);
//
//        }

        ArrayList<String> list = new ArrayList<>();

        for (String tableOriginName : collection) {

            String tableMonth = tableOriginName.replace("fund_record", "");
            if (month.contains(tableMonth)) {

                list.add(tableOriginName);
            }
        }

        return list;
    }
}

 

shardingsphere的jdbc連接不能用springboot的 druid-spring-boot-starter ,只能用阿里的druid

 

    <!--mysql相關包開始-->
<!--    <dependency>-->
<!--      <groupId>com.alibaba</groupId>-->
<!--      <artifactId>druid-spring-boot-starter</artifactId>-->
<!--      <version>${druid.version}</version>-->
<!--    </dependency>-->

    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.20</version>
    </dependency>

    <!--shardingsphere-->
    <dependency>
      <groupId>org.apache.shardingsphere</groupId>
      <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
      <version>4.1.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shardingsphere</groupId>
      <artifactId>sharding-jdbc-spring-namespace</artifactId>
      <version>4.1.1</version>
    </dependency>

 

 

官網:https://shardingsphere.apache.org/document/legacy/4.x/document/cn/overview/

 


免責聲明!

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



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