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<BindingTableRule> bindingTableRules = new ArrayList<BindingTableRule>();
       // 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<Date> {
 
    private final String tablePrefix;
 
    @Override
    public String doEqualSharding(final Collection<String> availableTargetNames, final ShardingValue<Date> shardingValue) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMM");
        return tablePrefix +formatter.format(shardingValue.getValue());
    }
 
    @Override
    public Collection<String> doInSharding(final Collection<String> availableTargetNames, final ShardingValue<Date> shardingValue) {
        Collection<String> 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<String> doBetweenSharding(final Collection<String> availableTargetNames, final ShardingValue<Date> shardingValue) {
        Collection<String> result = new LinkedHashSet<>();
        DateFormat sdf = new SimpleDateFormat("yyyyMM");
        Range<Date> 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;
    }
}

是的,既然你按照日期来分表,这说明你每日产生的数据是非常大的,这种情况,一般来说,产品设计上,都是需要根据时间段来查询的,不然这样做分表的意义何在?

既然做了分表,那么查询条件里面一般都要包含分片键,动态分片的话是必须包含分片键的。 静态分片可以不用,但是那就会所有的库和表都会查一遍。

转载于:https://blog.csdn.net/u012394095/article/details/81705382

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值