sharding-jdbc原理

sharding-jdbc原理

起男 659 2022-02-14

sharding-jdbc原理

当sharding-jdbc接收到一条sql语句时,会陆续执行:

  1. sql解析
  2. 查询优化
  3. sql路由
  4. sql改写
  5. sql执行
  6. 结构归并
  7. 返回结果

基本概念

逻辑表

水平拆分的数据表的总称

例如:用户表分为t_user_0和t_user_1,它们的逻辑表名称为t_user

真实表

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

例如:用户表分为t_user_0和t_user_1,它们就是真实表

数据节点

数据分片的最小单元,也就是这个表的数据分布情况。由数据源名称和数据表名称组成

例如:ds_0.t_user_0

绑定表

指分片规则一致的主表和子表

例如:t_user和t_user_info,都是按照user_id分片,绑定表之间的分区键完全相同,则它们两个互为绑定表

绑定表和非绑定表的区别是:多表关联查询时不会出现笛卡儿积的情况

公共表(广播表)

指所有分片数据源中都存在的表,表结构和表中的数据在每个数据库中均完全一致。适用于数据量不大且需要与海量数据进行关联查询的表

例如:字典表

分片键

用于分片的数据库字段,是将数据库和表水平拆分的关键字段

例如:t_user表根据user_id取模进行分片,user_id就是分片键

如果sql中没有分片键字段,则会进行全路由,性能较差

sharding-jdbc支持单字段分片,也支持多字段分片

分片算法

通过分片算法将数据分片,支持通过=、between、in分片。分片算法需要应用开发者自行实现,可以实现的灵活度非常高。包括:精确分片算法、范围分片算法、复合分片算法等

例如:where id=?将采用精确分片算法、where id between ? and ?采用范围分片算法、复合分片算法用于分片键有多个的情况

分片策略

包含分片键和分片算法,由于分片算法的独立性,将其独立抽离。真正可用于分片操作的是分片键+分片算法,也就是分片策略。内置的分片策略大致可分为尾数取模、哈希、范围、标签、时间等。

例如:行表达式配置分片策略,他采用groovy表达式表示,如:t_user_$->{user_id%2},表示t_user表根据user_id取模2

自增主键生成策略

通过在客户端生成自增主键替换以数据库原生自增主键的方式,做到分布式主键无重复

sql解析

sql解析的过程分为词法解析语法解析

词法解析器用于将sql解析为不可再分的原子符号,称为token。并根据不同数据库方言所提供的字典,将其归类为关键字、表达式、字面量和操作符。再使用语法解析器将sql转换为抽象语法树

sql路由

sql路由就是把针对逻辑表的数据操作映射到数据节点操作的过程

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

对于携带分片键的sql,根据分片键操作符不同可以划分为单片路由(分片键的操作符是等号)、多片路由(分片键的操作符是in)、和范围路由(分片键的操作符是between),不携带分片键的sql则采用广播路由

根据分片键的路由场景可以分为直接路由、标准路由、笛卡尔路由等

  • 标准路由:最推荐的方式,适用范围是不包含关联查询或仅包含绑定表之间关联查询的sql
  • 笛卡尔路由:查询效率较低,它无法根据绑定表的关系定位分片规则,因此非绑定表之间的关联查询需要拆解为笛卡儿积组合执行
  • 全库表路由:对于不携带分片键的sql,则采取广播路由。根据sql类型又可以分为全库表路由、全库路由、全实例路由、单播路由和阻断路由。其中全库表路由用于处理对数据库中与逻辑表相关的真实表操作,主要包括不带分片的dql(数据查询)、dml(数据操作)和ddl(数据定义)等

sql改写

用户面向逻辑表的sql,并不能直接在真实的数据库中执行,sql改写用于将逻辑sql改写为在真实数据库中可以正确执行的sql

比如:

  • select * from t_user 变为 select * from t_user_0
  • select name from t_user order by age 变为 select name,age from t_user order by age

sql执行

sharding-jdbc采用一套自动化的执行引擎,负责将路由和改写完成之后的真实sql安全且高效的发送到底层数据源执行

执行引擎的目标是自动化的平衡资源控制与执行效率,它能在以下两种模式下切换:

  • 内存限制模式:对一次操作所耗费的数据库连接数量不做限制。如果事件执行的sql需要对200张表做操作,则对每张表创建一个新的连接,并通过多线程的方式并发处理,以达成执行效率最大化

    适用于olap操作,可以通过放宽对数据库连接的限制提升系统吞吐量

  • 连接限制模式:严格控制对一次操作所耗费的数据库连接数量。如果实际执行的sql需要对200张表做操作,那么只会创建唯一的一个数据库连接,并对200张表做串行处理。如果一次操作中的分片散落在不同的数据库,仍然采用多线程处理,但每个库的每次操作仍然只创建一个唯一的数据库连接

    适用于oltp操作,oltp通常带有分片键,会路由到单一的分片,因此严格控制数据库连接,以保证在线系统数据库资源能够被更多的应用使用

结果归并

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

结果归并从功能上可分为遍历、排序、分组、分页和聚合,它们是组合关系而非互斥

从结构上分为流式归并、内存归并、装饰者归并。流式归并和内存归并是互斥的,装饰者归并可以在流式或内存归并之上做进一步处理

  • 内存归并:将所有分片结果集的数据都遍历存储在内存中,再通过统一的分组、排序以及聚合计算之后,再将其封装成逐条访问的数据结果集返回
  • 流式归并:是指每一次从数据库结果集中获取到的数据,都能够通过游标逐条获取的方式返回正确的单条数据,它与数据库原生的返回结果集的方式最为契合
  • 装饰者归并:是对所有的结果集进行统一的功能增强,比如归并时需要聚合sum前,在执行聚合计算前,都会通过内存或流式归并查询出结果集。因此,聚合归并是在其它归并类型上追加的归并能力,即装饰者模式