ShardingSphere
分片
分片键
用于分片的数据库字段,是将数据库(表)水平拆分的关键字段。例:将订单表中的订单主键的尾数取模分片,则订单主键为分片字段。 SQL中如果无分片字段,将执行全路由,性能较差。 除了对单分片字段的支持,ShardingSphere也支持根据多个字段进行分片。
分片算法
通过分片算法将数据分片,支持通过=
、BETWEEN
和IN
分片。分片算法需要应用方开发者自行实现,可实现的灵活度非常高。
- 精确分片算法
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_0
、t_order_1
、t_order_2
、t_order_3
这几个相应的表中。ModShardingAlgorithm
假设有t_order_0
、t_order_1
、t_order_2
、t_order_3
四张表,那么当order_id
取值为 13 的时候,其会将这条数据根据算法13 % 4 = 1
插入到t_order_1
表中。而如果面对的是范围值,例如11 - 12
,那么将会返回的是t_order_3
和t_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;
限制
不支持 HAVING
、UNION
、UNION ALL
事务
接口 ShardingSphereTransactionManager
定义了基础的事务行为,例如获取连接、开始事务、提交事务、回滚事务、是否处于事务中等方法。
事务类型有 LOCAL
、XA
、BASE
这三种,其中 XA
和 BASE
用于分布式事务,而 LOCAL
只用于本地事务。而其中 BASE
事务类型是基于 Seata
实现的。