ShardingSphere

ShardingSphere

分片

分片键

用于分片的数据库字段,是将数据库(表)水平拆分的关键字段。例:将订单表中的订单主键的尾数取模分片,则订单主键为分片字段。 SQL中如果无分片字段,将执行全路由,性能较差。 除了对单分片字段的支持,ShardingSphere也支持根据多个字段进行分片。

分片算法

通过分片算法将数据分片,支持通过=BETWEENIN分片。分片算法需要应用方开发者自行实现,可实现的灵活度非常高。

  • 精确分片算法 PreciseShardingAlgorithm: 用于处理使用单一键作为分片键的 =IN 进行分片的场景。
  • 范围分片算法 RangeShardingAlgorithm: 用于处理使用单一键作为分片键的 BETWEEN AND 进行分片的场景。
  • 复合分片算法 ComplexKeysShardingAlgorithm: 用于处理使用多键作为分片键进行分片的场景。
  • Hint 分片算法 HintShardingAlgorithm: 用于处理使用 Hint 行分片的场景。

分片策略

包含分片键和分片算法,由于分片算法的独立性,将其独立抽离。真正可用于分片操作的是分片键 + 分片算法,也就是分片策略。目前提供5种分片策略。

  • 标准分片策略
  • 复合分片策略
  • 行表达式分片策略: 使用 Groovy 表达式
  • Hint 分片策略
  • 不分片策略

行表达式语法说明

行表达式的使用非常直观,只需要在配置中使用${ expression }$->{ expression }标识行表达式即可。 目前支持数据节点和分片算法这两个部分的配置。行表达式的内容使用的是Groovy的语法,Groovy能够支持的所有操作,行表达式均能够支持。

${begin..end}表示范围区间

${[unit1, unit2, unit_x]}表示枚举值

(1) 行表达式 ${['online', 'offline']}_table${1..3} 解析为:

online_table1, online_table2, online_table3, offline_table1, offline_table2, offline_table3

(2) 数据节点配置

db0
  ├── t_order0 
  └── t_order1 
db1
  ├── t_order0 
  └── t_order1

行表达式简化为: db${0..1}.t_order${0..1}db$->{0..1}.t_order$->{0..1}

分片算法

PreciseShardingValue 包含表名、列名、以及列的取值:

public final class PreciseShardingValue<T extends Comparable<?>> implements ShardingValue {
    
    private final String logicTableName;
    
    private final String columnName;
    
    private final T value;
}

RangeShardingValue 包含表名、列名、以及某个范围的值的列表:

public final class RangeShardingValue<T extends Comparable<?>> implements ShardingValue {
    
    private final String logicTableName;
    
    private final String columnName;
    
    private final Range<T> valueRange;
}

分片算法如下图所示:

  • InlineShardingAlgorithm 能够解析表达式。例如表达式 t_order_$->{order_id % 4},其根据 order_id 字段对 4 取余后的值,将数据分发到 t_order_0t_order_1t_order_2t_order_3 这几个相应的表中。
  • ModShardingAlgorithm 假设有 t_order_0t_order_1t_order_2t_order_3 四张表,那么当 order_id 取值为 13 的时候,其会将这条数据根据算法 13 % 4 = 1 插入到 t_order_1 表中。而如果面对的是范围值,例如 11 - 12,那么将会返回的是 t_order_3t_order_0 这两个表。
  • HashModShardingAlgorithm 将字段的哈希值的绝对值,对表的数量进行取余。

归并

本节参考:知乎

  • 遍历归并底层采用链表合并即可
  • 排序归并底层采用优先级队列对多个 next() 进行归并
  • GROUP BY XX ORDER BY XX:分组和排序一致,采用流式归并;不一致要将所有结果加载至内存进行分组和聚合
  • 分页归并。分布式的场景中,将 LIMIT 10000000, 10 改写为 LIMIT 0, 10000010,才能保证其数据的正确性。Sharding-Sphere 会通过结果集的 next 方法将无需取出的数据全部跳过。但同时需要注意的是,由于排序的需要,大量的数据仍然 需要传输 (也就是需要耗费不必要的网络) 到 Sharding-Sphere 的内存空间。因此,采用 LIMIT 这种方式分页,并非最佳实践。由于 LIMIT 并不能通过索引查询数据,因此如果可以保证ID的连续性,通过ID进行分页是比较好的解决方案。
SELECT * FROM t_order WHERE id > 100000 AND id <= 100010 ORDER BY id;

或通过记录上次查询结果的最后一条记录的ID进行下一页的查询,例如:

SELECT * FROM t_order WHERE id > 10000000 LIMIT 10;

限制

不支持 HAVINGUNIONUNION ALL

事务

接口 ShardingSphereTransactionManager 定义了基础的事务行为,例如获取连接开始事务提交事务回滚事务是否处于事务中等方法。

事务类型有 LOCALXABASE 这三种,其中 XABASE 用于分布式事务,而 LOCAL 只用于本地事务。而其中 BASE 事务类型是基于 Seata 实现的。

参考