【分库分表】sharding-jdbc(shardingsphere)—分片策略

1. 分片维度

Sharding-JDBC认为对于分片策略存有两种维度:

  • 数据源分片策略(DatabaseShardingStrategy):数据被分配的目标数据源
  • 表分片策略(TableShardingStrategy):数据被分配的目标表

两种分片策略API完全相同,但是表分片策略是依赖于数据源分片策略的(即:先分库然后才有分表)
在这里插入图片描述

1.1 核心概念:

  • 逻辑表:水平拆分的数据库的相同逻辑和数据结构表的总称。

    例:订单数据根据主键尾数拆分为10张表,分别是t_order_0到t_order_9,他们的逻辑表名为t_order

  • 真实表:在分片的数据库中真实存在的物理表。

    即上个示例中的t_order_0到t_order_9

  • 数据节点:数据分片的最小单元。由数据源名称和数据表组成,例:ds_0.t_order_0。

  • 绑定表:分片规则一致的主表和子表。

    例如:t_order表和t_order_item表,均按照order_id分片,则此两张表互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升。举例说明,如果SQL为:

    SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
    

    在不配置绑定表关系时,假设分片键order_id将数值10路由至第0片,将数值11路由至第1片,那么路由后的SQL应该为4条,它们呈现为笛卡尔积:

    SELECT i.* FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
    
    SELECT i.* FROM t_order_0 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
    
    SELECT i.* FROM t_order_1 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
    
    SELECT i.* FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
    

    在配置绑定表关系后,路由的SQL应该为2条:

    SELECT i.* FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
    
    SELECT i.* FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
    

    其中t_order在FROM的最左侧,ShardingSphere将会以它作为整个绑定表的主表。 所有路由计算将会只使用主表的策略,那么t_order_item表的分片计算将会使用t_order的条件。故绑定表之间的分区键要完全相同。

  • 广播表:也叫公共表,指所有的分片数据源中都存在的表,表结构和表中的数据在每个数据库中都完全一致。例如字典表

  • 分片键:用于分片的数据库字段,是将数据库(表)进行水平拆分的关键字段。SQL中若没有分片字段,将会执行全路由,性能会很差。

    除了对单分片字段的支持,ShardingSphere也支持根据多个字段进行分片

  • 分片算法:通过分片算法将数据进行分片,支持通过=、BETWEEN和IN分片。分片算法需要由应用开发者自行实现,可实现的灵活度非常高。

    • 精确分片算法
      对应PreciseShardingAlgorithm,用于处理使用单一键作为分片键的=与IN进行分片的场景。需要配合StandardShardingStrategy使用。

    • 范围分片算法
      对应RangeShardingAlgorithm,用于处理使用单一键作为分片键的BETWEEN AND、>、<、>=、<=进行分片的场景。需要配合StandardShardingStrategy使用。

    • 复合分片算法
      对应ComplexKeysShardingAlgorithm,用于处理使用多键作为分片键进行分片的场景,包含多个分片键的逻辑较复杂,需要应用开发者自行处理其中的复杂度。需要配合ComplexShardingStrategy使用。

    • Hint分片算法
      对应HintShardingAlgorithm,用于处理使用Hint行分片的场景。需要配合HintShardingStrategy使用。

  • 分片策略:真正用于进行分片操作的是分片键+分片算法,也就是分片策略。在ShardingJDBC中一般采用基于Groovy表达式的inline分片策略,通过一个包含分片键的算法表达式来制定分片策略,如t_user_$->{u_id%8}标识根据u_id模8,分成8张表,表名称为t_user_0到t_user_7。

2. 分片算法

Sharding分片策略继承自ShardingStrategy,提供了5种分片策略:
在这里插入图片描述
由于分片算法和业务实现紧密相关,因此Sharding-JDBC并未提供内置分片算法,而是通过分片策略将各种场景提炼出来,提供更高层级的抽象,并提供接口让应用开发者自行实现分片算法。

首先普及下上面叫单分片、多分片:

  • 单分片 就是单个表被分库分表了
  • 多分片 就是2个表以上的表 被分库分表了,因此跨表查询会涉及到多分片

InlineShardingStrategy行表达式分片策略

Inline表达式分片策略。使用Groovy的Inline表达式,提供对SQL语句中的=和IN的分片操作支持。

InlineShardingStrategy只支持单分片键,对于简单的分片算法,可以通过简单的配置使用,从而避免繁琐的Java代码开发,如: tuser${user_id % 8} 表示t_user表按照user_id按8取模分成8个表,表名称为t_user_0到t_user_7。

表达式,简单配置,简单快捷

仅支持支持精确查询,不支持范围查询

配置参数: inline.shardingColumn 分片键;inline.algorithmExpression分片表达式

实现方式: 按照分片表达式来进行分片。

StandardShardingStrategy

只支持单分片键的标准分片策略,支持精确查询和范围查询

标准分片策略。提供对SQL语句中的=, IN和BETWEEN AND的分片操作支持。

StandardShardingStrategy只支持单分片键,提供PreciseShardingAlgorithmRangeShardingAlgorithm两个分片算法。

  • preciseAlgorithmClassName 指向一个实现了
    io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm接口的java类名,提供按照 = 或者 IN 逻辑的精确分片 ,是必选
  • rangeAlgorithmClassName 指向一个实现了
    io.shardingsphere.api.algorithm.sharding.standard.RangeShardingAlgorithm接口的java类名,提供按照Between 条件进行的范围分片。是可选的,如果不配置rangeAlgorithmClassName,SQL中的BETWEEN AND将按照全库路由处理。

配置参数:standard.sharding-column 分片键;standard.precisealgorithm-class-name 精确分片算法类名;standard.range-algorithmclass-name 范围分片算法类名

ComplexShardingStrategy

复合分片策略。提供对SQL语句中的=, IN和BETWEEN AND的分片操作支持。

ComplexShardingStrategy支持多分片键,由于多分片键之间的关系复杂,因此Sharding-JDBC并未做过多的封装,而是直接将分片键值组合以及分片操作符交于算法接口,完全由应用开发者实现,提供最大的灵活度。

支持更复杂的查询策略,进行优化。例如有这样的需求,主键id是计算路由的字段,而另个字段user_id没用在路由计算上,但是和主键是同一个规则,即分片相同,如果同时利用主键和user_id作为查询条件,用复杂策略,可以实现路由功能快速查询,节约速度,否则,不用复杂策略,只能全分区扫。

配置参数:complex.sharding-columns 分片键(多个);
complex.algorithm-class-name 分片算法实现类。

实现方式:
shardingColumn指定多个分片列。

algorithmClassName指向一个实现了
org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardi ngAlgorithm接口的java类名。提供按照多个分片列进行综合分片的算法。

HintShardingStrategy

通过Hint而非SQL解析的方式分片的策略。

不需要分片键的强制分片策略。这个分片策略,简单来理解就是说,他的分片键不再跟SQL语句相关联,而是用程序另行指定。对于一些复杂的情况,例如select count(*) from (select userid from t_user where userid in (1,3,5,7,9))这样的SQL语句,就没法通过SQL语句来指定一个分片键。这个时候就可以通过程序,给他另行执行一个分片键,例如在按userid奇偶分片的策略下,可以指定1作为分片键,然后自行指定他的分片策略。

配置参数:hint.algorithm-class-name 分片算法实现类。

实现方式:
algorithmClassName指向一个实现了
org.apache.shardingsphere.api.sharding.hint.HintShardingAlgorithm接口的java类名。 示例:
com.roy.shardingDemo.algorithm.MyHintShardingAlgorithm在这个算法类中,同样是需要分片键的。而分片键的指定是通过HintManager.addDatabaseShardingValue方法(分库)和
HintManager.addTableShardingValue(分表)来指定。

使用时要注意,这个分片键是线程隔离的,只在当前线程有效,所以通常建 议使用之后立即关闭,或者用try资源方式打开

而Hint分片策略并没有完全按照SQL解析树来构建分片策略,是绕开了SQL解析的,所有对某些比较复杂的语句,Hint分片策略性能有可能会比较好(情况太多了,无法一一分析)。

但是要注意,Hint强制路由在使用时有非常多的限制:

-- 不支持UNION
SELECT * FROM t_order1 UNION SELECT * FROM t_order2
INSERT INTO tbl_name (col1, col2,) SELECT col1, col2, … FROM tbl_name WHERE col3 = ?

-- 不支持多层子查询
SELECT COUNT(*) FROM (SELECT * FROM t_order o WHERE o.id IN (SELECT id FROM t_order WHERE status = ?))

-- 不支持函数计算。ShardingSphere只能通过SQL字面提取用于分片的值
SELECT * FROM t_order WHERE to_date(create_time, 'yyyy-mm-dd') = '2019-01-01';

NoneShardingStrategy

不分片的策略。

3. 自定义分片算法

Sharding提供了以下4种算法接口:

PreciseShardingAlgorithm
RangeShardingAlgorithm
HintShardingAlgorithm
ComplexKeysShardingAlgorithm

可以自己实现自定义的分片算法,下面以t_order_items表为例自己实现分片算法:

3.1 标准分片策略(StandardShardingStrategy)

3.1.1 a、PreciseShardingAlgorithm实现:(Precise处理 = 和 in 的路由)

        // 配置order_item表规则...
        TableRuleConfiguration orderItemTableRuleConfig = new TableRuleConfiguration();
        orderItemTableRuleConfig.setLogicTable("t_order_items");
        orderItemTableRuleConfig.setActualDataNodes("db${0..2}.t_order_items_${0..1}");
        // 自定义的分片算法实现
        StandardShardingStrategyConfiguration standardStrategy = new StandardShardingStrategyConfiguration("order_id",MyPreciseShardingAlgorithm.class.getName());

        // 配置分库策略
        orderItemTableRuleConfig.setDatabaseShardingStrategyConfig(standardStrategy);

        // 配置分表策略
        orderItemTableRuleConfig.setTableShardingStrategyConfig(standardStrategy);

        shardingRuleConfig.getTableRuleConfigs().add(orderItemTableRuleConfig);

        // 获取数据源对象
        DataSource dataSource = null;
        try {
            dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, new ConcurrentHashMap(), new Properties());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return dataSource;

自定义的分片算法,先继承接口,打印参数:

@Slf4j
public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
    @Override
    public String doSharding(Collection collection, PreciseShardingValue<Long> preciseShardingValue) {

        log.info("collection:" + JSON.toJSONString(collection) + ",preciseShardingValue:" + JSON.toJSONString(preciseShardingValue));
        return null;
    }
}

输出如下日志:(第一行路由是db,下一行是table):

2018-01-19 20:13:36,790 -2 collection:["db0","db1","db2"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","value":100}

……

2018-01-21 16:33:22,269 -2 collection:["t_order_items_0","t_order_items_1"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","value":100}

于是可以简单实现一个类似Inline配置的规则:

@Slf4j
public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<Long> preciseShardingValue) {
        log.info("collection:" + JSON.toJSONString(collection) + ",preciseShardingValue:" + JSON.toJSONString(preciseShardingValue));
        for (String name : collection) {
            if (name.endsWith(preciseShardingValue.getValue() % collection.size() + "")) {
                log.info("return name:"+name);
                return name;
            }
        }
        return null;
    }
}

IN 条件的处理示例:

==> Preparing: select id,order_id,unique_no,quantity,is_active,inserttime,updatetime from t_order_items where is_active = 1 AND order_id in ( ? , ? , ? ) 
==> Parameters: 100(Long), 101(Long), 102(Long)


//第一轮route筛选数据库(分片键路由规则):
09:55:09.634 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - collection:["db0","db1","db2"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","value":100}
09:55:13.758 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - return name:db1
09:55:17.767 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - collection:["db0","db1","db2"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","value":101}
09:55:21.361 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - return name:db2
09:55:23.127 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - collection:["db0","db1","db2"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","value":102}
09:55:24.190 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - return name:db0

//第二轮route按第一轮筛选到的db,逐个进行table的计算:
09:58:45.086 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - collection:["t_order_items_0","t_order_items_1"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","value":100}
09:58:46.725 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - return name:t_order_items_0
09:58:58.647 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - collection:["t_order_items_0","t_order_items_1"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","value":101}
09:59:02.197 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - return name:t_order_items_1
09:59:11.710 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - collection:["t_order_items_0","t_order_items_1"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","value":102}
09:59:12.604 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - return name:t_order_items_0
10:00:01.538 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - collection:["t_order_items_0","t_order_items_1"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","value":100}
10:00:01.538 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - return name:t_order_items_0
10:00:02.042 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - collection:["t_order_items_0","t_order_items_1"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","value":101}
10:00:02.042 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - return name:t_order_items_1
10:00:02.442 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - collection:["t_order_items_0","t_order_items_1"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","value":102}
10:00:02.442 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - return name:t_order_items_0
10:00:03.581 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - collection:["t_order_items_0","t_order_items_1"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","value":100}
10:00:03.581 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - return name:t_order_items_0
10:00:03.946 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - collection:["t_order_items_0","t_order_items_1"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","value":101}
10:00:03.946 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - return name:t_order_items_1
10:00:04.578 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - collection:["t_order_items_0","t_order_items_1"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","value":102}
10:00:04.578 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - return name:t_order_items_0

3.1.2 b. PreciseShardingAlgorithm + RangeShardingAlgorithm

@Slf4j
public class MyRangeShardingAlgorithm implements RangeShardingAlgorithm<Long> {
    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Long> rangeShardingValue) {
        log.info("Range collection:" + JSON.toJSONString(collection) + ",rangeShardingValue:" + JSON.toJSONString(rangeShardingValue));
        Collection<String> collect = new ArrayList<>();
        Range<Long> valueRange = rangeShardingValue.getValueRange();
        for (Long i = valueRange.lowerEndpoint(); i <= valueRange.upperEndpoint(); i++) {
            for (String each : collection) {
                if (each.endsWith(i % collection.size() + "")) {
                    collect.add(each);
                }
            }
        }
        return collect;
    }
}
22:17:35.318 logback-demo [http-nio-8082-exec-6] INFO s.j.demo.controller.OrderController - selectByOrderIds ,startNo:100,endNo:101

路由输出log:

-- 第一轮计算db
22:16:51.732 logback-demo [http-nio-8082-exec-6] INFO s.j.d.d.MyRangeShardingAlgorithm - Range collection:["db0","db1","db2"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","valueRange":{"empty":false}}

-- 第二轮计算table

22:17:16.325 logback-demo [http-nio-8082-exec-6] INFO s.j.d.d.MyRangeShardingAlgorithm - Range collection:["t_order_items_0","t_order_items_1"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","valueRange":{"empty":false}}
22:17:32.771 logback-demo [http-nio-8082-exec-6] INFO s.j.d.d.MyRangeShardingAlgorithm - Range collection:["t_order_items_0","t_order_items_1"],preciseShardingValue:{"columnName":"order_id","logicTableName":"t_order_items","valueRange":{"empty":false}}

路由到[db0,db1]X[t_order_items_0,t_order_items_1]表。

3.2 ComplexShardingStrategy

分库分表配置:user_id单键分库 + 【user_id+order_id】组合键分表

@Bean(name = "shardingComplexDataSource", destroyMethod = "close")
    @Qualifier("shardingComplexDataSource")
    public DataSource getComlpexShardingDataSource() {
        // 配置真实数据源
        Map<String, DataSource> dataSourceMap = new HashMap<>(3);

        List<String> dbNames = new ArrayList<>();
        dbNames.add("db0");
        dbNames.add("db1");
        dbNames.add("db2");

        for (String dbName : dbNames) {
            DruidDataSource dataSource = createDefaultDruidDataSource();
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource.setUrl("jdbc:mysql://localhost:3306/" + dbName);
            dataSource.setUsername("root");
            dataSource.setPassword("root");
            dataSourceMap.put(dbName, dataSource);
        }

        TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration();
        orderTableRuleConfig.setLogicTable("t_order");
        orderTableRuleConfig.setActualDataNodes("db${0..2}."+"t_order_${0..1}_${0..1}");

        /**分库采用单片键 user_id*/
        orderTableRuleConfig.setDatabaseShardingStrategyConfig(new StandardShardingStrategyConfiguration("user_id", MyPreciseShardingAlgorithm.class.getName()));
        /**分表采用双片键 user_id*/
        orderTableRuleConfig.setTableShardingStrategyConfig(new ComplexShardingStrategyConfiguration("user_id,order_id", MyComplexShardingAlgorithm.class.getName()));

        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTableRuleConfigs().add(orderTableRuleConfig);

        // 获取数据源对象
        DataSource dataSource = null;
        try {
            dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, new ConcurrentHashMap(), new Properties());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return dataSource;
    }

实现ComplexKeysShardingAlgorithm算法:

@Slf4j
public class MyComplexShardingAlgorithm implements ComplexKeysShardingAlgorithm {
    @Override
    public Collection<String> doSharding(Collection<String> collection, Collection<ShardingValue> shardingValues) {
        log.info("collection:" + JSON.toJSONString(collection) + ",shardingValues:" + JSON.toJSONString(shardingValues));

        Collection<Long> orderIdValues = getShardingValue(shardingValues, "order_id");
        Collection<Long> userIdValues = getShardingValue(shardingValues, "user_id");
        List<String> shardingSuffix = new ArrayList<>();
        /**例如:根据user_id + order_id 双分片键来进行分表*/
        //Set<List<Integer>> valueResult = Sets.cartesianProduct(userIdValues, orderIdValues);
        for (Long userIdVal : userIdValues) {
            for (Long orderIdVal : orderIdValues) {
                String suffix = userIdVal % 2 + "_" + orderIdVal % 2;
                collection.forEach(x -> {
                    if (x.endsWith(suffix)) {
                        shardingSuffix.add(x);
                    }
                });
            }
        }

        return shardingSuffix;
    }

    private Collection<Long> getShardingValue(Collection<ShardingValue> shardingValues, final String key) {
        Collection<Long> valueSet = new ArrayList<>();
        Iterator<ShardingValue> iterator = shardingValues.iterator();
        while (iterator.hasNext()) {
            ShardingValue next = iterator.next();
            if (next instanceof ListShardingValue) {
                ListShardingValue value = (ListShardingValue) next;
                /**例如:根据user_id + order_id 双分片键来进行分表*/
                if (value.getColumnName().equals(key)) {
                    return value.getValues();
                }
            }
        }
        return valueSet;
    }
}

运行示例:

16:53:16.267 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - collection:["db0","db1","db2"],preciseShardingValue:{"columnName":"user_id","logicTableName":"t_order","value":123}
16:53:16.267 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyPreciseShardingAlgorithm - return name:db0


16:53:16.740 logback-demo [http-nio-8082-exec-1] INFO s.j.d.d.MyComplexShardingAlgorithm - collection:["t_order_0_0","t_order_0_1","t_order_1_0","t_order_1_1"],shardingValues:[{"columnName":"order_id","logicTableName":"t_order","values":[321]},{"columnName":"user_id","logicTableName":"t_order","values":[123]}]

参考

【分库分表】sharding-jdbc—分片策略
Sharding JDBC(四) 分片策略一:标准分片策略StandardShardingStrategy

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值