随着项目运行时间逐渐增加,数据库中的数据也越来越多,虽然加索引,优化查询,但是数据量太大,还是会影响查询效率,也给数据库增加了负载。
再加上冷数据基本不使用的场景,决定采用分表来处理数据,从而来提高系统性能。
官方文档在这里。
Sharding-jdbc 定位是轻量级的java框架,在java 的JDBC层提供额外功能。它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。
文档很全,并且有三款产品的说明,分别是:Sharding jdbc 、Sharding-proxy、Sharding-sidecar(研发中)
本着想学技术,先实践写demo的原则,直接跳过SQL,解析引擎,路由、改写、归并引擎等说明,直接到配置界面。
配置的方式有很多种:
配置好之后,直接传入一个 分片算法即可。
// 配置数据源DataSource getShardingDataSource() throws SQLException { ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration(); shardingRuleConfig.getTableRuleConfigs().add(getOrderTableRuleConfiguration()); shardingRuleConfig.getBindingTableGroups().add("t_order");// 如果需要打印SQL new Properties 可以 设置一个属性 > io.shardingjdbc.core.constant.ShardingPropertiesConstant#SQL_SHOW return ShardingDataSourceFactory.createDataSource(createDataSourceMap(), shardingRuleConfig, new ConcurrentHashMap<>(), new Properties()); } // 针对不同的表可以有不同的策略 TableRuleConfiguration getOrderTableRuleConfiguration() { TableRuleConfiguration result = new TableRuleConfiguration(); result.setLogicTable("t_order"); result.setActualDataNodes("ds${0..1}.t_order${0..1}"); result.setTableShardingStrategyConfig(shardingRuleConfiguration()); return result; } @Bean public ShardingStrategyConfiguration shardingRuleConfiguration() { return new MyHintShardingStrategyConfiguration("order_id","com.test.config.MyHintShardingAlgorithm"); } Map<String, DataSource> createDataSourceMap() { Map<String, DataSource> result = new HashMap<>(); result.put("ds0", DataSourceUtil.createDataSource("ds0")); result.put("ds1", DataSourceUtil.createDataSource("ds1")); return result; }
// 分片路由:找到对应的表节点@Override public RoutingResult route() { TableRule tableRule = shardingRule.getTableRule(logicTableName); List<ShardingValue> databaseShardingValues = getDatabaseShardingValues(tableRule); List<ShardingValue> tableShardingValues = getTableShardingValues(tableRule); // 获取下面表名的地方 Collection<String> routedDataSources = routeDataSources(tableRule, databaseShardingValues); Collection<DataNode> routedDataNodes = new LinkedList<>(); for (String each : routedDataSources) { routedDataNodes.addAll(routeTables(tableRule, each, tableShardingValues)); } return generateRoutingResult(routedDataNodes); }// sharding方法只有这里才会调用,他有一个条件,就是传入的 tableShardingValues 不可以为空 private Collection<DataNode> routeTables(final TableRule tableRule, final String routedDataSource, final List<ShardingValue> tableShardingValues) { Collection<String> availableTargetTables = tableRule.getActualTableNames(routedDataSource); Collection<String> routedTables = tableShardingValues.isEmpty() ? availableTargetTables : shardingRule.getTableShardingStrategy(tableRule).doSharding(availableTargetTables, tableShardingValues);// **这里** Preconditions.checkState(!routedTables.isEmpty(), "no table route info"); Collection<DataNode> result = new LinkedList<>(); for (String each : routedTables) { result.add(new DataNode(routedDataSource, each)); } return result; }// 传入的参数是这里传入的:由于我这里使用强制路由所以走这里private List<ShardingValue> getTableShardingValuesFromHint(final Collection<String> shardingColumns) { List<ShardingValue> result = new ArrayList<>(shardingColumns.size()); for (String each : shardingColumns) { Optional<ShardingValue> shardingValue = HintManagerHolder.getTableShardingValue(new ShardingKey(logicTableName, each)); if (shardingValue.isPresent()) { result.add(shardingValue.get()); } } return result; }
public HintShardingStrategy(final HintShardingAlgorithm shardingAlgorithm) { this.shardingColumns = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); this.shardingAlgorithm = shardingAlgorithm; }
发现shardingColumns 一直是空的,也没有方法可以添加(自定义添加也不行,因为ShardingStrategy是通过对应的ShardingStrategyConfiguration#build方法生成的),所以肯定不会走到路由的地方。
排查到这里,就找到了一个修改的方法--重写 ShardingStrategy ,随意给 columns 赋值不为空即可。
// 自定义新的构造函数,给 shardingColumns 赋值public MyHintShardingStrategy(Collection<String> shardingColumns, final HintShardingAlgorithm shardingAlgorithm) { this.shardingColumns = new TreeSet<>(shardingColumns); this.shardingAlgorithm = shardingAlgorithm; }
重新运行项目,发现一切按想要的来。
不知道是自己配置的原因,还是打开的方式不对,反正通过这种方式实现了表的分片。
像项目提的issue入口在这里,等待回复
如有不对还请大神们指教!