java配置强制分片,doSharding不执行的疑问

有业务需要需要灵活配置数据源根据租户进行分库
采用了shardingsphere5.1.1,使用JAVA代码进行配置强制路由
在@ RaigorJiang老师的指导下进行了部分配置
相关关键代码如下:
路由规则配置部分:

ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
shardingRuleConfig.setDefaultTableShardingStrategy(new NoneShardingStrategyConfiguration());
shardingRuleConfig.setDefaultDatabaseShardingStrategy(new HintShardingStrategyConfiguration("com.xxx.TenantHintShardingAlgorithm"));
Properties props = new Properties();
props.setProperty("algorithmClassName", TenantHintShardingAlgorithm.class.getName());
props.setProperty("strategy", ClassBasedShardingAlgorithmStrategyType.HINT.name());
shardingRuleConfig.getShardingAlgorithms().put("tableShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("CLASS_BASED", props));

HintSharding配置部分

public class TenantHintShardingAlgorithm implements HintShardingAlgorithm<Long> {
	@Override
	public Collection<String> doSharding(Collection<String> availableTargetNames, HintShardingValue<Long> shardingValue) {
		return null;
	}

	@Override
	public void init() {

	}

	@Override
	public String getType() {
		return "TENANT_HINT";
	}
}

实际应用中发现,在项目中启动init方法会执行到,但是调用过程中doSharding不会执行
hintManager.setDataSourceName(“ds1”)也可以正常切换数据源
请问是因为没具体实现doSharding方法还是配置上有什么问题?

另外,HintShardingAlgorithm中必需实现的getType在这种配置方法下的作用是什么?

配置有误,请参考 这里createRuleConfiguration2 方法:
new HintShardingStrategyConfiguration 需要指定一个算法 key,而不是类名。

然后该 key 表示的算法,定义为 CLASS_BASED 形式,指向你的自定义算法,即可。

感谢老师的回复知道,但是还是不太理解”定义为 CLASS_BASED 形式,指向你的自定义算法“的具体做法,按自己的猜想,然后跟了一下源码,调整代码逻辑如下:

Properties props = new Properties();
props.setProperty("algorithmClassName", TenantHintShardingAlgorithm.class.getName());
props.setProperty("strategy", ClassBasedShardingAlgorithmStrategyType.HINT.name());
shardingRuleConfig.getShardingAlgorithms().put(TenantHintShardingAlgorithm.ALGORITHM_NAME, new ShardingSphereAlgorithmConfiguration("CLASS_BASED", props));

shardingRuleConfig.setDefaultTableShardingStrategy(new HintShardingStrategyConfiguration(TenantHintShardingAlgorithm.ALGORITHM_NAME));
shardingRuleConfig.setDefaultDatabaseShardingStrategy(new HintShardingStrategyConfiguration(TenantHintShardingAlgorithm.ALGORITHM_NAME));

算法中getType两种都试过,结果一样

public String getType() {
return “CLASS_BASED”;
}


public String getType() {
return TenantHintShardingAlgorithm.ALGORITHM_NAME;
}

还是init可以执行到,getType和doSharding在初始化和调用过程中都没有执行到

image

望老师不吝赐教

  1. 使用 CLASS_BASED 方式配置算法,是为了方便用户不必去配置 SPI,这种情况下 getType 是不会调用的。
  2. Hint 策略需要用户设置 hint 值后才会调用分片算法,否则拿什么去处理 doSharding 的逻辑呢?请参考 文档https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/special-api/sharding/hint/

感谢您的回复
我这边在业务逻辑里有使用

HintManager hintManager = HintManager.getInstance();
hintManager.setDataSourceName("ds_1");
hintManager.addDatabaseShardingValue("resource_type", "ds_0");
hintManager.addTableShardingValue("resource_type","ds_0");

其中hintManager.setDataSourceName(“ds_1”);这行代码是起作用的
但是doSharding这个方法还是没有进入

好的,我会再测试一下你的配置。

感谢回复

我这边有新的进展,顺便整理下现在的状态
1,两个数据源:ds_0和ds_1
2,测试表名:resource_type

分片配置

...
//定义分片规则
ShardingRuleConfiguration result = new ShardingRuleConfiguration();
//添加分片算法
Properties props = new Properties();
props.setProperty("algorithmClassName", TenantHintShardingAlgorithm.class.getName());
props.setProperty("strategy", ClassBasedShardingAlgorithmStrategyType.HINT.name());
result.getShardingAlgorithms().put(TenantHintShardingAlgorithm.ALGORITHM_NAME, new ShardingSphereAlgorithmConfiguration("CLASS_BASED", props));

//配置固定表算法
ShardingTableRuleConfiguration resourceTypeRule = new ShardingTableRuleConfiguration("resource_type","ds_${0..1}.resource_type");
resourceTypeRule.setTableShardingStrategy(new NoneShardingStrategyConfiguration());
resourceTypeRule.setDatabaseShardingStrategy(new HintShardingStrategyConfiguration(TenantHintShardingAlgorithm.ALGORITHM_NAME));
result.getTables().add(resourceTypeRule);

//配置默认分片算法
result.setDefaultTableShardingStrategy(new NoneShardingStrategyConfiguration());
result.setDefaultDatabaseShardingStrategy(new HintShardingStrategyConfiguration(TenantHintShardingAlgorithm.ALGORITHM_NAME));
...

业务逻辑中代码

...
HintManager hintManager = HintManager.getInstance();
//hintManager.setDataSourceName("ds_1");
//hintManager.addDatabaseShardingValue("resource_type", 1);
//hintManager.addTableShardingValue("resource_type",2);
hintManager.setDatabaseShardingValue("ds_0");
...
hintManager.close();
...

现在配置中使用hintManager.setDatabaseShardingValue(“ds_0”);方式添加hint参数是可以执行到”doSharding()“的
但是前提需要配置指定表,只配置DefaultStrategy的话,"doSharding()"不会执行到

OK,确实是这样的。
也就是说这张表要出现在 sharding table rule 的规则中,且它没有指定的分片策略,这个时候才会去使用默认的分片策略。
因为没有出现在 sharding table rule 中的表,在 SS 中被认为是单表 single table,不需要分片。

为简化配置,你可以移除 setTableShardingStrategy 和 setDatabaseShardingStrategy 的操作,只要设置 dataNodes 就行了:

//配置固定表算法
ShardingTableRuleConfiguration resourceTypeRule = new ShardingTableRuleConfiguration("resource_type","ds_${0..1}.resource_type");
result.getTables().add(resourceTypeRule);

好的,谢谢

顺便提个需求不知道合不合适

我看论坛和github的issue里有不少想让logicTable可以通配的需求,比如"*"什么的,就可以通配所有的表,不知道官方有没有这方面的考虑。

你不嫌麻烦的话可以在applitationrunner里面用sql查完,更新shardingsphere的context。

京ICP备2021015875号