ShardingSphere-JDBC 5.1 动态更新actual-data-nodes
前言
项目中根据年份进行分表(主要存放着日志类数据),每年会生成新的表,所以actual-data-nodes
属性需要在不重新启动的前提下动态更新,网上找了好多相关的修改办法,大多都是4.x版本的,最后在官方Github的Issues中找到了相应的解答
链接:https://github.com/apache/shardingsphere/issues/16725
上述链接的答疑中,已经提供了相应的解决办法,我在尝试的过程中想到了一种更简便的办法(其实就是把文中的两种方式结合了一下),下面细说
actual-data-nodes
回答中提到actual-data-nodes
除了使用Groovy
表达式(如下)的方式以外
actual-data-nodes: ds.table_name_$->{2023...2024}
还可以使用静态方法的形式配置(我在官方文档中没看到这种形式,可能是没找到),如下
actual-data-nodes: ds.table_name_$->{com.demo.util.LocalShardingDatabasesAndTablesUtils.getActualDataNodes()}
public class LocalShardingDatabasesAndTablesUtils {
public static int offset = 1;
public static List<String> getActualDataNodes() {
int startYear = 2023;
int endYear = LocalDate.now().getYear() + offset;
return LongStream.range(startYear, endYear)
.mapToObj(Long::toString)
.collect(Collectors.toList());
}
}
上述代码片段只是一种配置actual-data-nodes
的方式,并不能起到动态更新的作用,只会在项目初始化时执行一次
动态更新
那么如何动态更新呢,这里需要获取到ShardingSphereDataSource
数据源(我这里是Spring
直接注入进来的),代码如下
@Component
public class InitActualDataNodesAO {
@Resource
private ShardingSphereDataSource shardingSphereDataSource;
// ShardingSphere中默认值是logic_db,可以通过shardingsphere.schema.name在spring的配置文件中修改
private final String schemaName = "logic_db";
public void testSharding() {
this.reloadShardRuleActualDataNodes(shardingSphereDataSource, schemaNameForTOrder);
}
private void reloadShardRuleActualDataNodes(ShardingSphereDataSource dataSource, String schemaName) {
// Context manager.
org.apache.shardingsphere.mode.manager.ContextManager contextManager = dataSource.getContextManager();
// Rule configuration.
Collection<RuleConfiguration> ruleConfigList = dataSource.getContextManager()
.getMetaDataContexts()
.getMetaData(schemaName)
.getRuleMetaData()
.getConfigurations();
// update context
contextManager.alterRuleConfiguration(schemaName, ruleConfigList);
}
}
原文中的方式是通过代码生成新的Groovy
表达式,然后创建新的分片规则,获取并将旧规则中除actual-data-nodes
以外的所有配置复制到新的规则中,之后执行contextManager.alterRuleConfiguration(schemaName, newRuleConfigList)
从而达到更新的目的。
而在我的代码示例中,因为actual-data-nodes
配置的方式是静态方法,方法内编写了根据时间动态生成对应的分片集合,只需要在合适的时机调用contextManager.alterRuleConfiguration(schemaName, ruleConfigList)
方法,ShardingSphere-JDBC
就会重新调用我们提供的静态方法,从而达到动态更新actual-data-nodes
的目的
总结
官方的问答中已经提供了一种更新方法,我这里只是取巧,简化了一些步骤,具体使用哪种形式,还需大家自行考虑
另外具体更新的时机需要结合项目中的业务调整,比如我示例中的业务是每年生成一张新的表,也就是每年年初或上年年末执行即可,写在定时任务中即可,而且由于actual-data-nodes
是根据代码生成的,在项目重启后,也会根据我们自己编写的逻辑生成保持最新状态,不需要手动修改,至于具体的生成逻辑,根据项目业务实际情况调整即可。
希望能帮到大家,少走弯路。