HintShardingAlgorithm的使用问题

这个话题也许与 通过 SQL comment 进行强制路由 - Apache ShardingSphere - OpenSEC (sphere-ex.com) 有关.
通过ShardingSphere 5.0.0的源码, 我注意到这样的Example.
org.apache.shardingsphere.example.sharding.raw.jdbc.hint.ModuloHintShardingAlgorithm类 ,它实现了 强制路由 :: ShardingSphere (apache.org) 提到的 org.apache.shardingsphere.sharding.api.sharding.hint.HintShardingAlgorithm 接口.

public final class ModuloHintShardingAlgorithm implements HintShardingAlgorithm<Long> {
    
    @Override
    public void init() {
    }
    
    @Override
    public Collection<String> doSharding(final Collection<String> availableTargetNames, final HintShardingValue<Long> shardingValue) {
        Collection<String> result = new LinkedList<>();
        for (String each : availableTargetNames) {
            for (Long value : shardingValue.getValues()) {
                if (each.endsWith(String.valueOf(value % 2))) {
                    result.add(each);
                }
            }
        }
        return result;
    }
    
    @Override
    public String getType() {
        return "HINT_TEST";
    }
}

但我感觉这样的应用似乎与CLASS_BASE( 分片算法 :: ShardingSphere )没有什么区别?而且这个类对应的配置文件,sharding-hint-databases-tables.yaml中,rules[0].shardingAlgorithms.hint_test只有type,没有algorithmClassName,这也是被允许的做法?

sharding-hint-databases-only.yaml存在rules[0].defaultDatabaseStrategy.hint.shardingAlgorithmName


ShardingSphere Doc提到Hint 的主要使用场景之一是分片字段不存在 SQL 和数据库表结构中,而存在于外部业务逻辑。
Example还有一个例子是CLASS_BASE的使用案例,即org.apache.shardingsphere.example.extension.sharding.algortihm.classbased.fixture.ClassBasedStandardShardingAlgorithmFixture

public final class ClassBasedStandardShardingAlgorithmFixture implements StandardShardingAlgorithm<Integer> {

    @Override
    public void init() {
    }

    @Override
    public String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<Integer> shardingValue) {
        for (String each : availableTargetNames) {
            if (each.endsWith(String.valueOf(shardingValue.getValue() % 2))) {
                return each;
            }
        }
        return null;
    }

    @Override
    public Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeShardingValue<Integer> shardingValue) {
        return availableTargetNames;
    }

    @Override
    public String getType() {
        return null;
    }
}

就给出的例子,我看不出org.apache.shardingsphere.example.extension.sharding.algortihm.classbased.fixture.ClassBasedStandardShardingAlgorithmFixtureorg.apache.shardingsphere.example.sharding.raw.jdbc.hint.ModuloHintShardingAlgorithm的使用上的区别,希望有朋友能解答我的疑惑.

很抱歉我提出问题的时候没看到org.apache.shardingsphere.example.sharding.raw.jdbc.ShardingHintRawExample,现在我知道它和CLASS_BASE的区别了.:rofl:
不过, 社区有没有通过Spring Bean去封装它的例子? 或者,这一处的java.sql.Statement来执行SQL语句的方式,即statement.execute("SELECT i.* FROM t_order o, t_order_item i WHERE o.order_id = i.order_id"),怎么样转化为便于Mybatis使用的形式? 对我来说Mybatis的动态SQL在mapper.xml内配置更方便.

Mybatis 和 jdbc 使用方式上应该是没有什么区别的,HintManager api 是通过ThreadLocal 的方式来实现强制路由的,应该只需要把事例中操作 HintManager 的部分移动到自己的业务代码中就可以了。

1 个赞

@tuichenchuxin 我可以简单的理解为 Connection connection = dataSource.getConnection();Statement statement = connection.createStatement()移除,直接在try语块内调取Mapper层的方法吗?还是需要将这两句替换为其他语句?

@tuichenchuxin 还有一个让我疑惑的事情,org.apache.shardingsphere.example.sharding.raw.jdbc.ShardingHintRawExample可以通过try-catch语句块来处理HintManager.
org.apache.shardingsphere.example.proxy.hint.ProxyHintExample为什么也可以通过try-catch语句块来处理HintManager?在Java语言之外的异构语言,或者就是SQLyog这样的MySQL GUI是怎么处理HintManager的呢?

非java 语言应该没有办法操作 HintManager api. ProxyHintExample 中的例子并没有操作 HintManager.

@tuichenchuxin

  • 这,那org.apache.shardingsphere.example.proxy.hint.ProxyHintExampleprivate static void setHintValue(final Statement statement) throws SQLException, 意味着shardingsphere 5.0.0DistSQL已经可以通过mysql:mysql-connector-java这样的驱动执行了? 这与之前我从 menghaoran 收到的回答出现偏差, 什么情况下在Java应用上执行的语句不走JDBC驱动而走Proxy代理?
  • 还是说我理解错了,通过JDBC驱动连接Proxy代理也算走Proxy代理?

image

  • 通过 RAL :: ShardingSphere (apache.org) 一节,我是否可以理解为此时的hintManager不会像 强制路由 :: ShardingSphere (apache.org) 那样, 需要在操作结束时调用 hintManager.close() 来清除 ThreadLocal 中的内容。而必须通过clear hint这条DistSQL语句来每次清除hint的路由?
  • 那看起来不允许多个项目同时写同一shardingsphere Proxy上的add sharding hint table_value t_order = 100,否则很容易在clear hint执行后冲突?

这里是直接将 proxy 作为数据库来连接的,数据库当然可以通过jdbc 来连接。 孟浩然的意思是 distSql 要通过proxy,而不是直接通过 sharding-jdbc。
对于通过 DistSql 来清理 Hint 的问题,我暂时还不大清楚,后面我再看下代码。

1 个赞

感谢你的解答! 我一直认为聊天记录内的JDBC指的是mysql的JDBC驱动,而不是ShardingSphere-JDBC.

@tuichenchuxin

  • 我看了 属性配置 :: ShardingSphere (apache.org) ,这处的每个请求一个独立的线程应该怎么理解,是意味着项目的数据库连接池的连接(以Druid为例的话),如果因为条件限制自动切换, 那在那之前遗留的,类似add sharding hint table_value xx = yy这样对Hint的配置就自动失效,因此还得用类似show [sharding / readwrite_splitting] hint status的语句来做业务逻辑中的判断条件?
  • 我指的场景是直接在项目连接ShardingSphere-Proxy,而不引入ShardingSphere-JDBC,因此得以使用Alibaba Druid的情况.

从配置说明来看,应该是为了保证 Hint 的设置有效,所以给每个请求保留一个单独的线程,如果再接入 DRUID 来管理线程池的话,可能要看是否还能保证是原有线程了。
其实如果用 proxy 的话,你可以考虑使用增加注释来实现强制路由。

1 个赞

wow,这么看来sql commnet hint是个非常棒的特性,避开了我之前疑惑的问题.很期待5.0.1.

京ICP备2021015875号