强制路由

简介

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

1.分片字段不存在SQL中、数据库表结构中,而存在于外部业务逻辑。

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

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

配置Hint分片算法

Hint分片算法需要用户实现org.apache.shardingsphere.api.sharding.hint.HintShardingAlgorithm接口。ShardingSphere在进行Routing时,如果发现LogicTable的TableRule采用了Hint的分片算法,将会从HintManager中获取分片值进行路由操作。

参考配置如下:

  1. shardingRule:
  2. tables:
  3. t_order:
  4. actualDataNodes: demo_ds_${0..1}.t_order_${0..1}
  5. databaseStrategy:
  6. hint:
  7. algorithmClassName: org.apache.shardingsphere.userAlgo.HintAlgorithm
  8. tableStrategy:
  9. hint:
  10. algorithmClassName: org.apache.shardingsphere.userAlgo.HintAlgorithm
  11. defaultTableStrategy:
  12. none:
  13. defaultKeyGenerator:
  14. type: SNOWFLAKE
  15. column: order_id
  16. props:
  17. sql.show: true

获取HintManager

  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)的强制主库路由

获取HintManager

与基于暗示(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. }

example

hint-example