强制路由

简介

ShardingSphere使用ThreadLocal管理分片键值进行Hint强制路由。可以通过编程的方式向HintManager中添加分片条件,该分片条件仅在当前线程内生效。Hint方式主要使用场景:

1.分片字段不存在SQL中、数据库表结构中,而存在于外部业务逻辑。因此,通过Hint实现外部指定分片结果进行数据操作。

2.强制在主库进行某些数据操作。

基于暗示(Hint)的数据分片

配置

使用hint进行强制数据分片,需要使用HintManager搭配分片策略配置共同使用。若DatabaseShardingStrategy配置了Hint分片算法,则可使用HintManager进行分库路由结果的注入。同理,若TableShardingStrategy配置了Hint分片算法,则同样可使用HintManager进行分表路由结果的注入。所以使用Hint之前,需要配置Hint分片算法。

参考代码如下:

  1. shardingRule:
  2. tables:
  3. t_order:
  4. actualDataNodes: demo_ds_${0..1}.t_order_${0..1}
  5. databaseStrategy:
  6. hint:
  7. algorithmClassName: io.shardingsphere.userAlgo.HintAlgorithm
  8. tableStrategy:
  9. hint:
  10. algorithmClassName: io.shardingsphere.userAlgo.HintAlgorithm
  11. defaultTableStrategy:
  12. none:
  13. defaultKeyGeneratorClassName: io.shardingsphere.core.keygen.DefaultKeyGenerator
  14. props:
  15. sql.show: true

实例化

  1. HintManager hintManager = HintManager.getInstance();

添加分片键值

  • 使用hintManager.addDatabaseShardingValue来添加数据源分片键值。
  • 使用hintManager.addTableShardingValue来添加表分片键值。

分库不分表情况下,强制路由至某一个分库时,可使用hintManager.setDatabaseShardingValue方式添加分片。通过此方式添加分片键值后,将跳过SQL解析和改写阶段,从而提高整体执行效率。

清除分片键值

分片键值保存在ThreadLocal中,所以需要在操作结束时调用hintManager.close()来清除ThreadLocal中的内容。

hintManager实现了AutoCloseable接口,可推荐使用try with resource自动关闭。

完整代码示例

  1. // Sharding database and table with using hintManager.
  2. String sql = "SELECT * FROM t_order";
  3. try (HintManager hintManager = HintManager.getInstance();
  4. Connection conn = dataSource.getConnection();
  5. PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
  6. hintManager.addDatabaseShardingValue("t_order", 1);
  7. hintManager.addTableShardingValue("t_order", 2);
  8. try (ResultSet rs = preparedStatement.executeQuery()) {
  9. while (rs.next()) {
  10. // ...
  11. }
  12. }
  13. }
  14. // Sharding database without sharding table and routing to only one database with using hintManger.
  15. String sql = "SELECT * FROM t_order";
  16. try (HintManager hintManager = HintManager.getInstance();
  17. Connection conn = dataSource.getConnection();
  18. PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
  19. hintManager.setDatabaseShardingValue(3);
  20. try (ResultSet rs = preparedStatement.executeQuery()) {
  21. while (rs.next()) {
  22. // ...
  23. }
  24. }
  25. }

基于暗示(Hint)的强制主库路由

实例化

与基于暗示(Hint)的数据分片相同。

设置主库路由

  • 使用hintManager.setMasterRouteOnly设置主库路由。

清除分片键值

与基于暗示(Hint)的数据分片相同。

完整代码示例

  1. String sql = "SELECT * FROM t_order";
  2. try (
  3. HintManager hintManager = HintManager.getInstance();
  4. Connection conn = dataSource.getConnection();
  5. PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
  6. hintManager.setMasterRouteOnly();
  7. try (ResultSet rs = preparedStatement.executeQuery()) {
  8. while (rs.next()) {
  9. // ...
  10. }
  11. }
  12. }