sharding-jdbc动态更新分片

场景:

sharding-jdbc动态更新分片规则


代码实现:

本实例采用的是通过类实现配置,需要数据源Map集合DataSourceMap、shrding-jdbc配置shardingConfig、定时执行更新节点逻辑ShardingTableRuleActualTablesRefreshSchedule

建立数据源Map集合的对应

@Configuration
public class DataSourceMapConfig {

    @Value("${jdbcurl}")
    private String url;

    @Value("${name}")
    private String username;

    @Value("${password}")
    private String password;

    @Value("${driver-class-name}")
    private String driverClassName;

    private Map<String, DataSource> dsMap = new HashMap<>();

    @PostConstruct
    public void init(){
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setUsername(username);
        hikariDataSource.setPassword(password);
        hikariDataSource.setJdbcUrl(url);
        hikariDataSource.setDriverClassName(driverClassName);
        dsMap.put("m1", hikariDataSource);
    }

    public Map<String, DataSource> getDataSourceMap(){
        return dsMap;
    }

}

配置分片策略,并创建shardingDataSource

@Configuration
public class ShardingConfig {

    @Autowired
    private DataSourceMapConfig dataSourceMapConfig;

    @Bean(name = "shardingDataSource")
    public DataSource getShardingDataSource() throws SQLException {
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        //分片表规则配置
        shardingRuleConfig.getTableRuleConfigs().add(getOrderTableRuleConfiguration());

        //设置默认表分片策略
		//shardingRuleConfig.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new PreciseModuloShardingTableAlgorithm()));
        //spring.shardingsphere.props.sql.show = true
        Properties properties = new Properties(); properties.put("sql.show","true");
        //创建ShardingDataSource数据源
        return ShardingDataSourceFactory.createDataSource(dataSourceMapConfig.getDataSourceMap(), shardingRuleConfig, properties);
    }

    private TableRuleConfiguration getOrderTableRuleConfiguration() {
        // 定义t_order表的分片策略
        TableRuleConfiguration result = new TableRuleConfiguration("t_order","m1.t_order_${[1,2]}");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id",new PreciseModuloShardingTableAlgorithm()));
        result.setKeyGeneratorConfig(getKeyGeneratorConfiguration());
        return result;
    }

    private KeyGeneratorConfiguration getKeyGeneratorConfiguration() {
    	//设置生成主键算法
        KeyGeneratorConfiguration result = new KeyGeneratorConfiguration("SNOWFLAKE","order_id");
        return result;
    }

定时执行更新节点逻辑

@Slf4j
@Component
@EnableScheduling
@Order
public class ShardingTableRuleActualTablesRefreshSchedule implements InitializingBean {

    private Logger logger = LoggerFactory.getLogger(ShardingTableRuleActualTablesRefreshSchedule.class);

    @Resource(name = "shardingDataSource")
    private DataSource dataSource;

    @Scheduled(cron = "0/10 * * * * ?")
    //刷新节点的逻辑,核心通过反射更新tableRule,
    public void actualTablesRefresh() throws Exception {
        logger.info("-----开始刷新表节点-----");
        ShardingDataSource shardingDataSource = (ShardingDataSource)dataSource;
        //运行时获取分片规则
        ShardingRule rule = shardingDataSource.getRuntimeContext().getRule();

        //获取分表策略集合
        Collection<TableRule> tableRules = rule.getTableRules();

        for (TableRule tableRule : tableRules) {
            //获取真实节点
            List<DataNode> actualDataNodes = tableRule.getActualDataNodes();

            Field actualDataNodesField = TableRule.class.getDeclaredField("actualDataNodes");
            Field modifiersField = Field.class.getDeclaredField("modifiers");
            modifiersField.setAccessible(true);
            modifiersField.setInt(actualDataNodesField, actualDataNodesField.getModifiers() & ~Modifier.FINAL);

            //数据源名
            String dataSourceName = actualDataNodes.get(0).getDataSourceName();
            //逻辑表名
            String logicTableName = tableRule.getLogicTable();
            //根据真实业务,新增节点的逻辑
            String tableName = actualDataNodes.get(actualDataNodes.size() - 1).getTableName();
            int index = (int)(tableName.charAt(tableName.length()-1))+1-'0';
            //新增节点
            actualDataNodes.add(new DataNode(dataSourceName+"."+logicTableName+"_"+index));

            actualDataNodesField.setAccessible(true);
            actualDataNodesField.set(tableRule, actualDataNodes);

            Set<String> actualTables = Sets.newHashSet();
            Map<DataNode, Integer> dataNodeIntegerMap = Maps.newHashMap();
            //更新actualTables、dataNodeIntegerMap
            AtomicInteger a = new AtomicInteger(0);
            actualDataNodes.forEach((dataNode -> {
                actualTables.add(dataNode.getTableName());
                if (a.intValue() == 0){
                    a.incrementAndGet();
                    dataNodeIntegerMap.put(dataNode, 0);
                }else {
                    dataNodeIntegerMap.put(dataNode, a.intValue());
                    a.incrementAndGet();
                }
            }));

            //动态刷新:actualTables
            Field actualTablesField = TableRule.class.getDeclaredField("actualTables");
            actualTablesField.setAccessible(true);
            actualTablesField.set(tableRule, actualTables);
            //动态刷新:dataNodeIndexMap
            Field dataNodeIndexMapField = TableRule.class.getDeclaredField("dataNodeIndexMap");
            dataNodeIndexMapField.setAccessible(true);
            dataNodeIndexMapField.set(tableRule, dataNodeIntegerMap);
            //动态刷新:datasourceToTablesMap
            Map<String, Collection<String>> datasourceToTablesMap = Maps.newHashMap();
            datasourceToTablesMap.put(dataSourceName, actualTables);
            Field datasourceToTablesMapField = TableRule.class.getDeclaredField("datasourceToTablesMap");
            datasourceToTablesMapField.setAccessible(true);
            datasourceToTablesMapField.set(tableRule, datasourceToTablesMap);
            logger.info("-----------------end----------------");

        }
    }

    @Override
    public void afterPropertiesSet() throws Exception{
        actualTablesRefresh();
    }

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值