共计 3053 个字符,预计需要花费 8 分钟才能阅读完成。
依据解析上下文匹配数据库和表的分片策略,并生成路由门路。
对于携带分片键的 SQL,依据分片键的不同能够划分为单片路由 (分片键的操作符是等号)、多片路由(分片键的操作符是 IN) 和范畴路由 (分片键的操作符是 BETWEEN)。
不携带分片键的 SQL 则采纳播送路由。
分片策略通常能够采纳由数据库内置或由用户方配置。
数据库内置的计划较为简单,内置的分片策略大抵可分为尾数取模、哈希、范畴、标签、工夫等。
由用户方配置的分片策略则更加灵便,能够依据应用方需要定制复合分片策略。
如果配合数据主动迁徙来应用,能够做到无需用户关注分片策略,主动由数据库中间层分片和均衡数据即可,进而做到使分布式数据库具备的弹性伸缩的能力。
在 ShardingSphere 的线路布局中,弹性伸缩将于 4.x 开启。
分片路由
用于依据分片键进行路由的场景,又细分为间接路由、规范路由和笛卡尔积路由这 3 种类型。
间接路由
满足间接路由的条件绝对刻薄,它须要通过 Hint(应用 HintAPI 间接指定路由至库表)形式分片,并且是只分库不分表的前提下,则能够防止 SQL 解析和之后的后果归并。
因而它的兼容性最好,能够执行包含子查问、自定义函数等简单状况的任意 SQL。间接路由还能够用于分片键不在 SQL 中的场景。例如,设置用于数据库分片的键为3
,
hintManager.setDatabaseShardingValue(3);
如果路由算法为 value % 2
,当一个逻辑库t_order
对应 2 个实在库 t_order_0
和t_order_1
时,路由后 SQL 将在 t_order_1
上执行。下方是应用 API 的代码样例:
String sql = "SELECT * FROM t_order";
try (HintManager hintManager = HintManager.getInstance();
Connection conn = dataSource.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {hintManager.setDatabaseShardingValue(3);
try (ResultSet rs = pstmt.executeQuery()) {while (rs.next()) {//...}
}
}
规范路由
规范路由是 ShardingSphere 最为举荐应用的分片形式,它的适用范围是不蕴含关联查问或仅蕴含绑定表之间关联查问的 SQL。
当分片运算符是等于号时,路由后果将落入单库(表),当分片运算符是 BETWEEN 或 IN 时,则路由后果不肯定落入惟一的库(表),因而一条逻辑 SQL 最终可能被拆分为多条用于执行的实在 SQL。
举例说明,如果依照 order_id
的奇数和偶数进行数据分片,一个单表查问的 SQL 如下:
SELECT * FROM t_order WHERE order_id IN (1, 2);
那么路由的后果应为:
SELECT * FROM t_order_0 WHERE order_id IN (1, 2);
SELECT * FROM t_order_1 WHERE order_id IN (1, 2);
绑定表的关联查问与单表查问复杂度和性能相当。举例说明,如果一个蕴含绑定表的关联查问的 SQL 如下:
SELECT * FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE order_id IN (1, 2);
那么路由的后果应为:
SELECT * FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE order_id IN (1, 2);
SELECT * FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE order_id IN (1, 2);
能够看到,SQL 拆分的数目与单表是统一的。
笛卡尔路由
笛卡尔路由是最简单的状况,它无奈依据绑定表的关系定位分片规定,因而非绑定表之间的关联查问须要拆解为笛卡尔积组合执行。
如果上个示例中的 SQL 并未配置绑定表关系,那么路由的后果应为:
SELECT * FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE order_id IN (1, 2);
SELECT * FROM t_order_0 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE order_id IN (1, 2);
SELECT * FROM t_order_1 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE order_id IN (1, 2);
SELECT * FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE order_id IN (1, 2);
笛卡尔路由查问性能较低,需谨慎应用。
播送路由
对于不携带分片键的 SQL,则采取播送路由的形式。依据 SQL 类型又能够划分为全库表路由、全库路由、全实例路由、单播路由和阻断路由这 5 种类型。
全库表路由
全库表路由用于解决对数据库中与其逻辑表相干的所有实在表的操作,次要包含不带分片键的 DQL 和 DML,以及 DDL 等。例如:
SELECT * FROM t_order WHERE good_prority IN (1, 10);
则会遍历所有数据库中的所有表,逐个匹配逻辑表和实在表名,可能匹配得上则执行。路由后成为
SELECT * FROM t_order_0 WHERE good_prority IN (1, 10);
SELECT * FROM t_order_1 WHERE good_prority IN (1, 10);
SELECT * FROM t_order_2 WHERE good_prority IN (1, 10);
SELECT * FROM t_order_3 WHERE good_prority IN (1, 10);
全库路由
全库路由用于解决对数据库的操作,包含用于库设置的 SET 类型的数据库治理命令,以及 TCL 这样的事务管制语句。
在这种状况下,会依据逻辑库的名字遍历所有合乎名字匹配的实在库,并在实在库中执行该命令,例如:
SET autocommit=0;
在 t_order
中执行,t_order
有 2 个实在库。则理论会在 t_order_0
和t_order_1
上都执行这个命令。
全实例路由
全实例路由用于 DCL 操作,受权语句针对的是数据库的实例。无论一个实例中蕴含多少个 Schema,每个数据库的实例只执行一次。例如:
CREATE USER customer@127.0.0.1 identified BY '123';
这个命令将在所有的实在数据库实例中执行,以确保 customer 用户能够拜访每一个实例。
单播路由
单播路由用于获取某一实在表信息的场景,它仅须要从任意库中的任意实在表中获取数据即可。例如:
DESCRIBE t_order;
t_order 的两个实在表 t_order_0,t_order_1 的形容构造雷同,所以这个命令在任意实在表上抉择执行一次。
阻断路由
阻断路由用于屏蔽 SQL 对数据库的操作,例如:
USE order_db;
这个命令不会在实在数据库中执行,因为 ShardingSphere 采纳的是逻辑 Schema 的形式,无需将切换数据库 Schema 的命令发送至数据库中。
路由引擎的整体构造划分如下图。