ShardingSphere数据分片内核原理及源码流程


ShardingSphere数据分片这一部分内核主要是解析引擎、路由引擎、改写引擎、执行引擎、归并引擎五部分。这里主要是对这五部分进行剖析。

在数据分片这块Sharding-JDBC和Sharding-Proxy内核原理这一块是一致的。

官方文档有详细:https://shardingsphere.apache.org/document/legacy/4.x/document/cn/features/

解析引擎

解析过程分为词法解析和语法解析。 词法解析器用于将SQL拆解为不可再分的原子符号,称为Token。并根据不同数据库方言所提供的字典,将其归类为关键字,表达式,字面量和操作符。 再使用语法解析器将SQL转换为抽象语法树(简称AST, Abstract Syntax Tree)。

例如对下面一条SQL语句:

SELECT id, name FROM t_user WHERE status = 'ACTIVE' AND age > 18

会被解析成下面这样一颗树:

为了便于理解,抽象语法树中的关键字的 Token 用绿色表示,变量的 Token 用红色表示,灰色表示需要进⼀步拆分。通过对抽象语法树的遍历,可以标记出所有可能需要改写的位置。SQL的一次解析过程是不可逆的,所有token按SQL原本的顺序依次进行解析,性能很高。并且在解析过程中,需要考虑各种数据库SQL方言的异同,提供不同的解析模版。

其中,SQL解析是整个分库分表产品的核心,其性能和兼容性是最重要的衡量指标。ShardingSphere在1.4.x之前采用的是性能较快的Druid作为SQL解析器。1.5.x版本后,采用自研的SQL解析器,针对分库分表场景,采取对SQL半理解的方式,提高SQL解析的性能和兼容性。然后从3.0.x版本后,开始使用ANLTR作为SQL解析引擎。这是个开源的SQL解析引擎,ShardingSphere在使用ANLTR时,还增加了一些AST的缓存功能。针对ANLTR4的特性,官网建议尽量采用PreparedStatement的预编译方式来提高SQL执行的性能。

sql解析整体结构:

路由引擎

根据解析上下文匹配数据库和表的分片策略,生成路由路径。

ShardingSphere的分片策略:

  • 单片路由(分片键的操作符是等号)
  • 多片路由(分片键的操作符是IN)
  • 范围路由(分片键的操作符是Between)
  • 不携带分片键的SQL则是广播路由。

分片策略通常可以由数据库内置也可以由用户方配置。内置的分片策略大致可分为尾数取模、哈希、范围、标签、时间等。 由用户方配置的分片策略则更加灵活,可以根据使用方需求定制复合分片策略。

实际使用时,应尽量使用分片路由,明确路由策略。因为广播路由影响过大,不利于集群管理及扩展。

  • 全库表路由:对于不带分片键的DQL、DML以及DDL语句,会遍历所有的库表,逐一执行。例如 SELECT * FROM t_order WHERE good_prority IN (1, 10)
  • 全库路由:对数据库的操作都会遍历所有真实库。 例如 set autocommit=0
  • 全实例路由:对于DCL语句,每个数据库实例只执行一次,例如 CREATE USER customer@127.0.0.1 identified BY ‘123’
  • 仅需要从任意库中获取数据即可。 例如 DESCRIBE t_order
  • 阻断路由:屏蔽SQL对数据库的操作。例如 USE order_db。就不会在真实库中执行,因为针对虚拟表操作,不需要切换数据库

改写引擎

用户只需要面向逻辑库和逻辑表来写SQL,最终由ShardigSphere的改写引擎将SQL改写为在真实数据库中可以正确执行的语句。SQL改写分为正确性改写和优化改写。

执行引擎

ShardingSphere并不是简单的将改写过的SQL丢到数据库去执行,ShardingSphere需要平衡资源和控制执行效率。

试想一下调用方本身只是执行一条SQL但经过ShardingSqohere改写过后就会有10条8条的SQL要去数据库执行,这些SQL会占有大量的连接,想来也是不合适的。ShardingSphere就在执行引擎进行了控制。

ShardingSphere提供了一种解决思路。它提出了连接模式的概念,在连接模式中分为内存限制模式和连接限制模式。

内存限制模式

内存限制模式对所操作的数据库连接不做限制,假使你要对200个数据库进行操作,那就创建200个连接。通过多线程并发处理,使执行效率最大化。优先选择流式归并,防止出现内存溢出和频繁GC

连接限制模式

ShardingSphere严格控制对一次操作所耗费的数据库连接数量。 如果实际执行的SQL需要对某数据库实例中的200张表做操作,那么只会创建唯一的数据库连接,并对其200张表串行处理。 如果一次操作中的分片散落在不同的数据库,仍然采用多线程处理对不同库的操作,但每个库的每次操作仍然只创建一个唯一的数据库连接。这样即可以防止对一次请求对数据库连接占用过多所带来的问题。该模式始终选择内存归并。

内存限制模式适用于OLAP操作,可以通过放宽对数据库连接的限制提升系统吞吐量,耗时较久; 连接限制模式适用于OLTP操作,耗时较短。

在maxConnectionSizePerQuery允许的范围内,当一个连接需要执行的请求数量大于1时,意味着当前的数据库连接无法持有相应的数据结果集,则必须采用内存归并; 反之,当一个连接需要执行的请求数量等于1时,意味着当前的数据库连接可以持有相应的数据结果集,则可以采用流式归并。

每一次的连接模式的选择,是针对每一个物理数据库的。也就是说,在同一次查询中,如果路由至一个以上的数据库,每个数据库的连接模式不一定一样,它们可能是混合存在的形态。

归并引擎

将从各个数据节点获取的多数据结果集,组合成为一个结果集并正确的返回至请求客户端,称为结果归并。

其中,流式归并是指以一条一条数据的方式进行归并,而内存归并是将所有结果集都查询到内存中,进行统一归并。

ShardingSphere的SPI扩展点

SPI(Service Provide Interface)

SPI就是一种为接口寻找服务发现的机制。将装配的控制权放在程序外面,而不再代码里面指定。这样如果我们要扩展一个类的实现不需要改写代码,只需要在外部实现接口就可以实现可拔插的原则。

约定:在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。

jdk提供服务实现查找的一个工具类:java.util.ServiceLoader

ShardingSphere的SPI扩展点

ShardingSphere的开发思想是对源码中主体流程封闭,而对SPI开放

官网:https://shardingsphere.apache.org/document/current/cn/dev-manual/

官网开发者手册里面有介绍各种ShardingSphere SPI扩展机制

源码流程图


文章作者: dm
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 dm !
评论
 上一篇
RocketMQ集群搭建 RocketMQ集群搭建
环境准备java版本:1.8 操作系统:CentOS7 安装包:https://rocketmq.apache.org/dowloading/releases/ 我这里选择的是4.7.1版本的rocketMQ RocketMQ 集群搭建注:
2023-12-05
下一篇 
ShardingSphere基本概念及快速入门 ShardingSphere基本概念及快速入门
Apache ShardingSphere 是一套开源的分布式数据库解决方案组成的生态圈,它由 JDBC、Proxy 和 Sidecar(规划中)这 3 款既能够独立部署,又支持混合部署配合使用的产品组成。 它们均提供标准化的数据水平扩展、
2023-10-20
  目录