分库分表

sharding-jdbc系列之按月动态分表
前言
sharding-jdbc默认是不支持在程序的运行过程中动态的创建表的,如果需要做到动态的按月分表,所有的表需要提前创建好哦, 比如,你可以把这两年的表全部建立好。或者另外写个程序,专门用来创建表,具体怎么做,你们自己选择,本文主要是讲,如果通过sharding-jdbc实现按月动态分表。

代码实现
设置数据源的时候,给该表设置分表规则

java代码

    @Bean
public ShardingRule shardingRule(DataSourceRule dataSourceRule){
    //具体分库分表策略
    TableRule userTableRule = TableRule.builder("t_user")
            .actualTables(Arrays.asList("t_user_00", "t_user_01"))
            .tableShardingStrategy(new TableShardingStrategy("user_id", new ModuloTableShardingAlgorithm()))
            .dataSourceRule(dataSourceRule)
            .build();
    TableRule stuTableRule = TableRule.builder("t_stu")
            .actualTables(Arrays.asList("t_stu"))
            .tableShardingStrategy(new TableShardingStrategy("id", new TestTableShardingAlgorithm()))
            .dataSourceRule(dataSourceRule)
            .build();
    // 按月动态分表
    TableRule orderTableRule = TableRule.builder("t_order").
            tableShardingStrategy(new TableShardingStrategy("createTime",
                    new SingleKeyDynamicModuloTableShardingAlgorithm("t_order_"))).
            dataSourceRule(dataSourceRule).dynamic(true).build();
    //绑定表策略,在查询时会使用主表策略计算路由的数据源,因此需要约定绑定表策略的表的规则需要一致,可以一定程度提高效率
    List bindingTableRules = new ArrayList();
   // bindingTableRules.add(new BindingTableRule(Arrays.asList(userTableRule,stuTableRule)));
    return ShardingRule.builder()
            .dataSourceRule(dataSourceRule)
            .tableRules(Arrays.asList(userTableRule,stuTableRule,orderTableRule))
            .bindingTableRules(bindingTableRules)
            .databaseShardingStrategy(new DatabaseShardingStrategy("id", new ModuloDatabaseShardingAlgorithm()))
            .tableShardingStrategy(new TableShardingStrategy("user_id", new ModuloTableShardingAlgorithm()))
            .build();
}

上面截图的代码,是我的一个小例子,动态分表主要看这一段代码

 // 按月动态分表
 TableRule orderTableRule = TableRule.builder("t_order").
                tableShardingStrategy(new TableShardingStrategy("createTime",
                        new SingleKeyDynamicModuloTableShardingAlgorithm("t_order_"))).
                dataSourceRule(dataSourceRule).dynamic(true).build();
逻辑表t_order , 通过createTime进行分表, 分片规则类为SingleKeyDynamicModuloTableShardingAlgorithm

PS : 这里有一个属性比较重要,dynamic设置为true表示动态分表,否则是无效的。

yaml方式

dataSource:
  db0: !!org.apache.commons.dbcp.BasicDataSource
    driverClassName: org.h2.Driver
    url: jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
    username: sa
    password: 
    maxActive: 100
  db1: !!org.apache.commons.dbcp.BasicDataSource
    driverClassName: org.h2.Driver
    url: jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
    username: sa
    password: 
    maxActive: 100

tables:
  config:
    dynamic: true
  t_order: 
    dynamic: true
    databaseStrategy: &db001
      shardingColumns: order_id
      algorithmClassName: com.dangdang.ddframe.rdb.sharding.config.yaml.algorithm.SingleAlgorithm
    tableStrategy: &table001
      shardingColumns: id
      algorithmExpression: t_order_${id.longValue() % 2}

  t_order_item:
    dynamic: true
    #绑定表中其余的表的策略与第一张表的策略相同
    databaseStrategy: *db001
    tableStrategy: *table001

#默认数据库分片策略
defaultDatabaseStrategy:
  shardingColumns: order_id, user_id
  algorithmExpression: t_order_${id.longValue() % 2}
defaultTableStrategy:
  shardingColumns: id, order_id
  algorithmClassName: com.dangdang.ddframe.rdb.sharding.config.yaml.algorithm.MultiAlgorithm

    分片策略
@RequiredArgsConstructor
public final class SingleKeyDynamicModuloTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm {
    private final String tablePrefix;

    @Override
    public String doEqualSharding(final Collection availableTargetNames, final ShardingValue shardingValue) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMM");
        return tablePrefix +formatter.format(shardingValue.getValue());
    }

    @Override
    public Collection doInSharding(final Collection availableTargetNames, final ShardingValue shardingValue) {
        Collection result = new LinkedHashSet<>(shardingValue.getValues().size());
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMM");
        for (Date value : shardingValue.getValues()) {
            result.add(tablePrefix + formatter.format(value));
        }
        return result;
    }

    @Override
    public Collection doBetweenSharding(final Collection availableTargetNames, final ShardingValue shardingValue) {
        Collection result = new LinkedHashSet<>();
        DateFormat sdf = new SimpleDateFormat("yyyyMM");
        Range ranges = shardingValue.getValueRange();
        Date startTime = ranges.lowerEndpoint();
        Date endTime = ranges.upperEndpoint();
        // range.lowerEndpoint() = 2018-08-01
        // range.upperEndpoint() = 2018-10-01
        // 此处应该返回  tablePrefix+201808 , tablePrefix+201809,tablePrefix+201810,
        Calendar cal = Calendar.getInstance();

        while (startTime.getTime()<=endTime.getTime()){
            result.add(tablePrefix + sdf.format(startTime));
            cal.setTime(startTime);//设置起时间
            cal.add(Calendar.MONTH,1);
            startTime = cal.getTime();
        }
        return result;
    }
}

你可能感兴趣的:(jpa)