分布式数据库中间件ShardingSphere

分布式数据库

​ 对于主流的非关系型数据库,如 ElasticSearch、Kafka等,它们的架构天然就是分布式的,包含数据分片、副本等概念,能够轻松应对高并发请求和海量数据存储。然而对于起步最早的传统关系型数据库,如MySQL、Oracle、SQLServer等,它们大都不是分布式数据库

分库分表产品:

  • Apache ShardingSphere
  • MyCat

Apache ShardingSphere

Apache ShardingSphere是一款分布式数据库生态系统,可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。

官方文档:https://shardingsphere.apache.org/document/current/cn/overview/

开源地址:https://github.com/apache/shardingsphere

发展历史

​ Sharding-JDBC 项目于2016年发布开源,逐步发展为后来的 ShardingSphere 生态体系,ShardingSphere 已于 2020 年 4 月成为 Apache 软件基金会的顶级项目。image-20221229113102958

设计理念

​ Apache ShardingSphere 设计哲学为 Database Plus,旨在构建异构数据库上层的标准和生态。它关注如何充分合理地利用数据库的计算和存储能力,而并非实现一个全新的数据库。它站在数据库的上层视角,关注它们之间的协作多于数据库自身。

功能特性

  1. 数据分片
  2. 读写分离
  3. 分布式事务
  4. 高可用
  5. 数据加密
  6. 数据脱敏
  7. 影子库
  8. 数据迁移
  9. 流量治理
  10. 可观测性

产品功能

特性 定义
数据分片 数据分片,是应对海量数据存储与计算的有效手段。ShardingSphere 基于底层数据库提供分布式数据库解决方案,可以水平扩展计算和存储。
分布式事务 事务能力,是保障数据库完整、安全的关键技术,也是数据库的核心技术。基于 XA 和 BASE 的混合事务引擎,ShardingSphere 提供在独立数据库上的分布式事务功能,保证跨数据源的数据安全。
读写分离 读写分离,是应对高压力业务访问的手段。基于对 SQL 语义理解及对底层数据库拓扑感知能力,ShardingSphere 提供灵活的读写流量拆分和读流量负载均衡。
高可用 高可用,是对数据存储计算平台的基本要求。ShardingSphere 提供基于原生或 Kubernetes 环境下数据库集群的分布式高可用能力。
数据迁移 数据迁移,是打通数据生态的关键能力。ShardingSphere 提供跨数据源的数据迁移能力,并可支持重分片扩展。
联邦查询 联邦查询,是面对复杂数据环境下利用数据的有效手段。ShardingSphere 提供跨数据源的复杂查询分析能力,实现跨源的数据关联与聚合。
数据加密 数据加密,是保证数据安全的基本手段。ShardingSphere 提供完整、透明、安全、低成本的数据加密解决方案。
影子库 在全链路压测场景下,ShardingSphere 支持不同工作负载下的数据隔离,避免测试数据污染生产环境。

数据分片

​ 传统的将数据集中存储至单一节点的解决方案,在性能、可用性和运维成本这三方面已经难于满足海量数据的场景。

​ 从性能方面来说,由于关系型数据库大多采用 B+ 树类型的索引,在数据量超过阈值的情况下,索引深度的增加也将使得磁盘访问的 IO 次数增加,进而导致查询性能的下降; 同时,高并发访问请求也使得集中式数据库成为系统的最大瓶颈。

​ 从可用性的方面来讲,服务化的无状态性,能够达到较小成本的随意扩容,这必然导致系统的最终压力都落在数据库之上。 而单一的数据节点,或者简单的主从架构,已经越来越难以承担。数据库的可用性,已成为整个系统的关键。

​ 从运维成本方面考虑,当一个数据库实例中的数据达到阈值以上,对于 DBA 的运维压力就会增大。 数据备份和恢复的时间成本都将随着数据量的大小而愈发不可控。一般来讲,单一数据库实例的数据的阈值在 1TB 之内,是比较合理的范围。

​ 数据分片指按照某个维度将存放在单一数据库中的数据分散地存放至多个数据库或表中以达到提升性能瓶颈以及可用性的效果。 数据分片的有效手段是对关系型数据库进行分库分表。分库和分表均可以有效的避免由数据量超过可承受阈值而产生的查询瓶颈。 除此之外,分库还能够用于有效的分散对数据库单点的访问量;分表虽然无法缓解数据库压力,但却能够提供尽量将分布式事务转化为本地事务的可能,一旦涉及到跨库的更新操作,分布式事务往往会使问题变得复杂。 使用多主多从的分片方式,可以有效的避免数据单点,从而提升数据架构的可用性。

​ 通过分库和分表进行数据的拆分来使得各个表的数据量保持在阈值以下,以及对流量进行疏导应对高访问量,是应对高并发和海量数据系统的有效手段。 数据分片的拆分方式又分为垂直分片水平分片

垂直分片

​ 按照业务拆分的方式称为垂直分片,又称为纵向拆分,它的核心理念是专库专用。 在拆分之前,一个数据库由多个数据表构成,每个表对应着不同的业务。而拆分之后,则是按照业务将表进行归类,分布到不同的数据库中,从而将压力分散至不同的数据库。 下图展示了根据业务需要,将用户表和订单表垂直分片到不同的数据库的方案。

image-20230313212455978

​ 垂直分片往往需要对架构和设计进行调整。通常来讲,是来不及应对互联网业务需求快速变化的;而且,它也并无法真正的解决单点瓶颈。 垂直拆分可以缓解数据量和访问量带来的问题,但无法根治。如果垂直拆分之后,表中的数据量依然超过单节点所能承载的阈值,则需要水平分片来进一步处理。

水平分片

​ 水平分片又称为横向拆分。 相对于垂直分片,它不再将数据根据业务逻辑分类,而是通过某个字段(或某几个字段),根据某种规则将数据分散至多个库或表中,每个分片仅包含数据的一部分。 例如:根据主键分片,偶数主键的记录放入 0 库(或表),奇数主键的记录放入 1 库(或表),如下图所示。

​ 水平分片从理论上突破了单机数据量处理的瓶颈,并且扩展相对自由,是数据分片的标准解决方案。

image-20230313213107933

挑战与目标

挑战

​ 虽然数据分片解决了性能、可用性以及单点备份恢复等问题,但分布式的架构在获得了收益的同时,也引入了新的问题。

​ 面对如此散乱的分片之后的数据,应用开发工程师和数据库管理员对数据库的操作变得异常繁重就是其中的重要挑战之一。 他们需要知道数据需要从哪个具体的数据库的子表中获取。

​ 另一个挑战则是,能够正确的运行在单节点数据库中的 SQL,在分片之后的数据库中并不一定能够正确运行。 例如,分表导致表名称的修改,或者分页、排序、聚合分组等操作的不正确处理。

​ 跨库事务也是分布式的数据库集群要面对的棘手事情。 合理采用分表,可以在降低单表数据量的情况下,尽量使用本地事务,善于使用同库不同表可有效避免分布式事务带来的麻烦。 在不能避免跨库事务的场景,有些业务仍然需要保持事务的一致性。 而基于 XA 的分布式事务由于在并发度高的场景中性能无法满足需要,并未被互联网巨头大规模使用,他们大多采用最终一致性的柔性事务代替强一致事务。

目标

​ 尽量透明化分库分表所带来的影响,让使用方尽量像使用一个数据库一样使用水平分片之后的数据库集群,是 Apache ShardingSphere 数据分片模块的主要设计目标。

应用场景

海量数据高并发的 OLTP 场景

由于关系型数据库大多采用 B+ 树类型的索引,在数据量超过阈值的情况下,索引深度的增加也将使得磁盘访问的 IO 次数增加,进而导致查询性能的下降。通过 ShardingSphere 数据分片,按照某个业务维度,将存放在单一数据库中的数据分散地存放至多个数据库或表中,可以达到提升性能的效果。通过使用 ShardingSphere-JDBC 接入端,可以满足高并发的 OLTP 场景下的性能要求。

海量数据实时分析 OLAP 场景

在传统的数据库架构中,如果用户想要进行数据分析,需要先使用 ETL 工具,将数据同步至数据平台中,然后再进行数据分析,使用 ETL 工具会导致数据分析的实效性大打折扣。ShardingSphere-Proxy 提供静态入口以及异构语言的支持,独立于应用程序部署,适用于实时分析的 OLAP 场景。

核心概念

逻辑表

相同结构的水平拆分数据库(表)的逻辑名称,是 SQL 中表的逻辑标识。 例:订单数据根据主键尾数拆分为 10 张表,分别是 t_order_0t_order_9,他们的逻辑表名为 t_order

物理表

在水平拆分的数据库中真实存在的物理表(真实表)。 即上个示例中的 t_order_0t_order_9

绑定表

指分片规则一致的一组分片表。 使用绑定表进行多表关联查询时,必须使用分片键进行关联,否则会出现笛卡尔积关联或跨库关联,从而影响查询效率。 例如:t_order 表和 t_order_item 表,均按照 order_id 分片,并且使用 order_id 进行关联,则此两张表互为绑定表关系。 绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升。 举例说明,如果 SQL 为:

SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

在不配置绑定表关系时,假设分片键 order_id 将数值 10 路由至第 0 片,将数值 11 路由至第 1 片,那么路由后的 SQL 应该为 4 条,它们呈现为笛卡尔积:

SELECT i.* FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

SELECT i.* FROM t_order_0 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

SELECT i.* FROM t_order_1 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

SELECT i.* FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

在配置绑定表关系,并且使用 order_id 进行关联后,路由的 SQL 应该为 2 条:

SELECT i.* FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

SELECT i.* FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

其中 t_order 表由于指定了分片条件,ShardingSphere 将会以它作为整个绑定表的主表。 所有路由计算将会只使用主表的策略,那么 t_order_item 表的分片计算将会使用 t_order 的条件。

广播表

​ 指所有的分片数据源中都存在的表,表结构及其数据在每个数据库中均完全一致。 适用于数据量不大且需要与海量数据的表进行关联查询的场景,例如:字典表。

单表

​ 指所有的分片数据源中仅唯一存在的表。 适用于数据量不大且无需分片的表。

数据节点

​ 数据分片的最小单元,由数据源名称和真实表组成。 例:ds_0.t_order_0。 逻辑表与真实表的映射关系,可分为均匀分布和自定义分布两种形式。

数据分片的最小单元,由数据源名称和真实表组成。 例:ds_0.t_order_0。 逻辑表与真实表的映射关系,可分为均匀分布和自定义分布两种形式。

均匀分布

指数据表在每个数据源内呈现均匀分布的态势, 例如:

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

数据节点的配置如下:

db0.t_order0, db0.t_order1, db1.t_order0, db1.t_order1

自定义分布

指数据表呈现有特定规则的分布, 例如:

db0
  ├── t_order0
  └── t_order1
db1
  ├── t_order2
  ├── t_order3
  └── t_order4

数据节点的配置如下:

db0.t_order0, db0.t_order1, db1.t_order2, db1.t_order3, db1.t_order4

分片

分片策略

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

分片键

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

分片算法

用于将数据分片的算法,支持 =>=<=><BETWEENIN 进行分片。 分片算法可由开发者自行实现,也可使用 Apache ShardingSphere 内置的分片算法语法糖,灵活度非常高。

自动化分片算法

分片算法语法糖,用于便捷的托管所有数据节点,使用者无需关注真实表的物理分布。 包括取模、哈希、范围、时间等常用分片算法的实现。

自定义分片算法

提供接口让应用开发者自行实现与业务实现紧密相关的分片算法,并允许使用者自行管理真实表的物理分布。 自定义分片算法又分为:

  • 标准分片算法

用于处理使用单一键作为分片键的 =INBETWEEN AND><>=<= 进行分片的场景。

  • 复合分片算法

用于处理使用多键作为分片键进行分片的场景,包含多个分片键的逻辑较复杂,需要应用开发者自行处理其中的复杂度。

  • Hint 分片算法

用于处理使用 Hint 行分片的场景。

行表达式

行表达式是为了解决配置的简化与一体化这两个主要问题。在繁琐的数据分片规则配置中,随着数据节点的增多,大量的重复配置使得配置本身不易被维护。 通过行表达式可以有效地简化数据节点配置工作量。

对于常见的分片算法,使用 Java 代码实现并不有助于配置的统一管理。 通过行表达式书写分片算法,可以有效地将规则配置一同存放,更加易于浏览与存储。

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

${begin..end} 表示范围区间 ${[unit1, unit2, unit_x]} 表示枚举值

行表达式中如果出现连续多个 ${ expression }$->{ expression } 表达式,整个表达式最终的结果将会根据每个子表达式的结果进行笛卡尔组合。

例如,以下行表达式:

${['online', 'offline']}_table${1..3}

最终会解析为:

online_table1, online_table2, online_table3, offline_table1, offline_table2, offline_table3

分布式主键

​ 传统数据库软件开发中,主键自动生成技术是基本需求。而各个数据库对于该需求也提供了相应的支持,比如 MySQL 的自增键,Oracle 的自增序列等。 数据分片后,不同数据节点生成全局唯一主键是非常棘手的问题。同一个逻辑表内的不同实际表之间的自增键由于无法互相感知而产生重复主键。 虽然可通过约束自增主键初始值和步长的方式避免碰撞,但需引入额外的运维规则,使解决方案缺乏完整性和可扩展性。

​ 目前有许多第三方解决方案可以完美解决这个问题,如 UUID 等依靠特定算法自生成不重复键,或者通过引入主键生成服务等。为了方便用户使用、满足不同用户不同使用场景的需求, Apache ShardingSphere 不仅提供了内置的分布式主键生成器,例如 UUID、SNOWFLAKE,还抽离出分布式主键生成器的接口,方便用户自行实现自定义的自增主键生成器

读写分离

​ 面对日益增加的系统访问量,数据库的吞吐量面临着巨大瓶颈。 对于同一时刻有大量并发读操作和较少写操作类型的应用系统来说,将数据库拆分为主库和从库,主库负责处理事务性的增删改操作,从库负责处理查询操作,能够有效的避免由数据更新导致的行锁,使得整个系统的查询性能得到极大的改善。

​ 通过一主多从的配置方式,可以将查询请求均匀的分散到多个数据副本,能够进一步的提升系统的处理能力。 使用多主多从的方式,不但能够提升系统的吞吐量,还能够提升系统的可用性,可以达到在任何一个数据库宕机,甚至磁盘物理损坏的情况下仍然不影响系统的正常运行。

​ 与将数据根据分片键打散至各个数据节点的水平分片不同,读写分离则是根据 SQL 语义的分析,将读操作和写操作分别路由至主库与从库

image-20230314093303815

​ 读写分离的数据节点中的数据内容是一致的,而水平分片的每个数据节点的数据内容却并不相同。将水平分片读写分离联合使用,能够更加有效的提升系统性能。

挑战与目标

挑战

​ 读写分离虽然可以提升系统的吞吐量和可用性,但同时也带来了数据不一致的问题。 这包括多个主库之间的数据一致性,以及主库与从库之间的数据一致性的问题。 并且,读写分离也带来了与数据分片同样的问题,它同样会使得应用开发和运维人员对数据库的操作和运维变得更加复杂。 下图展现了将数据分片与读写分离一同使用时,应用程序与数据库集群之间的复杂拓扑关系。

目标

​ 透明化读写分离所带来的影响,让使用方尽量像使用一个数据库一样使用主从数据库集群,是 Apache ShardingSphere 读写分离模块的主要设计目标。

应用场景

主从数据库架构

​ 许多系统通过采用主从数据库架构的配置来提高整个系统的吞吐量,但是主从的配置也给业务的使用带来了一定的复杂性。接入 ShardingSphere,可以利用读写分离功能管理主从数据库,实现透明化的读写分离功能,让用户像使用一个数据库一样使用主从架构的数据库。

使用限制

  • 不处理主库和从库的数据同步
  • 不处理主库和从库的数据同步延迟导致的数据不一致
  • 不支持主库多写
  • 不处理主从库间的事务一致性。主从模型中,事务中的数据读写均用主库。

高可用

​ 高可用是现代系统的最基本诉求,作为系统基石的数据库,对于高可用的要求也是必不可少的。

​ 在存算分离的分布式数据库体系中,存储节点和计算节点的高可用方案是不同的。 对于有状态的存储节点来说,需要其自身具备数据一致性同步、探活、主节点选举等能力; 对于无状态的计算节点来说,需要感知存储节点的变化的同时,还需要独立架设负载均衡器,并具备服务发现和请求分发的能力。

​ Apache ShardingSphere 自身提供计算节点,并通过数据库作为存储节点。 因此,它采用的高可用方案是利用数据库自身的高可用方案做存储节点高可用,并自动识别其变化

挑战与目标

挑战

Apache ShardingSphere 需要自动感知多样化的存储节点高可用方案的同时,也能够动态集成对读写分离方案,是实现的主要挑战。

目标

尽可能的保证 7*24 小时不间断的数据库服务,是 Apache ShardingSphere 高可用模块的主要设计目标。

应用场景

​ 在大多数情况下,高可用搭配读写分离功能一起使用。当用户写库或读库关系发生变化时,ShardingSphere 可动态的感知并纠正内部的主从关系,进而保证读流量和写流量的正确路由。同时当从库宕机时,ShardingSphere 也可动态纠正存储节点的状态,保证读流量分发正确。

高可用类型

​ Apache ShardingSphere 不提供数据库高可用的能力,它通过第三方提供的高可用方案感知数据库主从关系的切换。 确切来说,Apache ShardingSphere 提供数据库发现的能力,自动感知数据库主从关系,并修正计算节点对数据库的连接。

动态读写分离

​ 高可用和读写分离一起使用时,读写分离无需配置具体的主库和从库。 高可用的数据源会动态的修正读写分离的主从关系,并正确地疏导读写流量。

使用限制

支持项

  • MySQL MGR 单主模式
  • MySQL 主从复制模式
  • openGauss 主从复制模式

不支持项

  • MySQL MGR 多主模式

分布式事务

数据库事务需要满足 ACID(原子性、一致性、隔离性、持久性)四个特性。

  • 原子性(Atomicity)指事务作为整体来执行,要么全部执行,要么全不执行;
  • 一致性(Consistency)指事务应确保数据从一个一致的状态转变为另一个一致的状态;
  • 隔离性(Isolation)指多个事务并发执行时,一个事务的执行不应影响其他事务的执行;
  • 持久性(Durability)指已提交的事务修改数据会被持久保存。

在单一数据节点中,事务仅限于对单一数据库资源的访问控制,称之为本地事务。 几乎所有的成熟的关系型数据库都提供了对本地事务的原生支持。 但是在基于微服务的分布式应用环境下,越来越多的应用场景要求对多个服务的访问及其相对应的多个数据库资源能纳入到同一个事务当中,分布式事务应运而生。

关系型数据库虽然对本地事务提供了完美的 ACID 原生支持。 但在分布式的场景下,它却成为系统性能的桎梏。 如何让数据库在分布式场景下满足 ACID 的特性或找寻相应的替代方案,是分布式事务的重点工作。

挑战与目标

挑战

​ 由于应用的场景不同,需要开发者能够合理的在性能功能之间权衡各种分布式事务。

​ 强一致的事务与柔性事务的 API 和功能并不完全相同,在它们之间并不能做到自由的透明切换。 在开发决策阶段,就不得不在强一致的事务和柔性事务之间抉择,使得设计和开发成本被大幅增加。

​ 基于 XA 的强一致事务使用相对简单,但是无法很好的应对互联网的高并发或复杂系统的长事务场景; 柔性事务则需要开发者对应用进行改造,接入成本非常高,并且需要开发者自行实现资源锁定和反向补偿。

目标

​ 整合现有的成熟事务方案,为本地事务、两阶段事务和柔性事务提供统一的分布式事务接口,并弥补当前方案的不足,提供一站式的分布式事务解决方案是 Apache ShardingSphere 分布式事务模块的主要设计目标。

​ ShardingSphere 对外提供 begin/commit/rollback 传统事务接口,通过 LOCAL,XA,BASE 三种模式提供了分布式事务的能力。

LOCAL 事务

LOCAL 模式基于 ShardingSphere 代理的数据库 begin/commit/rolllback 的接口实现, 对于一条逻辑 SQL,ShardingSphere 通过 begin 指令在每个被代理的数据库开启事务,并执行实际 SQL,并执行 commit/rollback。 由于每个数据节点各自管理自己的事务,它们之间没有协调以及通信的能力,也并不互相知晓其他数据节点事务的成功与否。 在性能方面无任何损耗,但在强一致性以及最终一致性方面不能够保证。

XA 事务

​ XA 事务采用的是 X/OPEN 组织所定义的 DTP 模型 所抽象的 AP(应用程序), TM(事务管理器)和 RM(资源管理器) 概念来保证分布式事务的强一致性。 其中 TM 与 RM 间采用 XA 的协议进行双向通信,通过两阶段提交实现。 与传统的本地事务相比,XA 事务增加了准备阶段,数据库除了被动接受提交指令外,还可以反向通知调用方事务是否可以被提交。 TM 可以收集所有分支事务的准备结果,并于最后进行原子提交,以保证事务的强一致性。

image-20230314000120913

​ XA 事务建立在 ShardingSphere 代理的数据库 xa start/end/prepare/commit/rollback/recover 的接口上。

​ 对于一条逻辑 SQL,ShardingSphere 通过 xa begin 指令在每个被代理的数据库开启事务,内部集成 TM,用于协调各分支事务,并执行 xa commit/rollback

​ 基于 XA 协议实现的分布式事务,由于在执行的过程中需要对所需资源进行锁定,它更加适用于执行时间确定的短事务。 对于长事务来说,整个事务进行期间对数据的独占,将会对并发场景下的性能产生一定的影响。

BASE 事务

如果将实现了 ACID 的事务要素的事务称为刚性事务的话,那么基于 BASE 事务要素的事务则称为柔性事务。 BASE 是基本可用、柔性状态和最终一致性这三个要素的缩写。

  • 基本可用(Basically Available)保证分布式事务参与方不一定同时在线;
  • 柔性状态(Soft state)则允许系统状态更新有一定的延时,这个延时对客户来说不一定能够察觉;
  • 最终一致性(Eventually consistent)通常是通过消息传递的方式保证系统的最终一致性。

在 ACID 事务中对隔离性的要求很高,在事务执行过程中,必须将所有的资源锁定。 柔性事务的理念则是通过业务逻辑将互斥锁操作从资源层面上移至业务层面。 通过放宽对强一致性要求,来换取系统吞吐量的提升。

基于 ACID 的强一致性事务和基于 BASE 的最终一致性事务都不是银弹,只有在最适合的场景中才能发挥它们的最大长处。 Apache ShardingSphere 集成了 Seata 作为柔性事务的使用方案。 可通过下表详细对比它们之间的区别,以帮助开发者进行技术选型。

LOCAL XA BASE
业务改造 需要 seata server
一致性 不支持 支持 最终一致
隔离性 不支持 支持 业务方保证
并发性能 无影响 严重衰退 略微衰退
适合场景 业务方处理不一致 短事务 & 低并发 长事务 & 高并发

应用场景

​ 在单机应用场景中,依赖数据库提供的事务即可满足业务上对事务 ACID 的需求。但是在分布式场景下,传统数据库解决方案缺乏对全局事务的管控能力,用户在使用过程中可能遇到多个数据库节点上出现数据不一致的问题。

​ ShardingSphere 分布式事务,为用户屏蔽了分布式事务处理的复杂性,提供了灵活多样的分布式事务解决方案,用户可以根据自己的业务场景在 LOCAL,XA,BASE 三种模式中,选择适合自己的分布式事务解决方案。

ShardingSphere XA 事务使用场景

​ 对于 XA 事务,提供了分布式环境下,对数据强一致性的保证。但是由于存在同步阻塞问题,对性能会有一定影响。适用于对数据一致性要求非常高且对并发性能要求不是很高的业务场景。

ShardingSphere BASE 事务使用场景

​ 对于 BASE 事务,提供了分布式环境下,对数据最终一致性的保证。由于在整个事务过程中,不会像 XA 事务那样全程锁定资源,所以性能较好。适用于对并发性能要求很高并且允许出现短暂数据不一致的业务场景。

ShardingSphere LOCAL 事务使用场景

​ 对于 LOCAL 事务,在分布式环境下,不保证各个数据库节点之间数据的一致性和隔离性,需要业务方自行处理可能出现的不一致问题。适用于用户希望自行处理分布式环境下数据一致性问题的业务场景。

两个产品

ShardingSphere‐JDBC

​ ShardingSphere‐JDBC 定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC和各种 ORM 框架。

  • 适用于任何基于 JDBC 的 ORM 框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template 或直接使用 JDBC;
  • 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, HikariCP 等;
  • 支持任意实现 JDBC 规范的数据库,目前支持 MySQL,PostgreSQL,Oracle,SQLServer 以及任何可使用 JDBC 访问的数据库。
image-20221229095227353
ShardingSphere‐JDBC ShardingSphere-Proxy
数据库 任意 MySQL/PostgreSQL
连接消耗数
异构语言 仅 Java 任意
性能 损耗低 损耗略高
无中心化
静态入口

ShardingSphere-Proxy

​ ShardingSphere-Proxy 定位为透明化的数据库代理端,通过实现数据库二进制协议,对异构语言提供支持。 目前提供 MySQL 和 PostgreSQL 协议,透明化数据库操作,对 DBA 更加友好。

  • 向应用程序完全透明,可直接当做 MySQL/PostgreSQL 使用;
  • 兼容 MariaDB 等基于 MySQL 协议的数据库,以及 openGauss 等基于 PostgreSQL 协议的数据库;
  • 适用于任何兼容 MySQL/PostgreSQL 协议的的客户端,如:MySQL Command Client, MySQL Workbench, Navicat 等。
image-20221229095603433

运行模式

Apache ShardingSphere 提供了两种运行模式:

  • 单机模式
  • 集群模式

单机模式

​ 单机模式适用于工程师在本地搭建 Apache ShardingSphere 环境。

集群模式

​ 提供了多个 Apache ShardingSphere 实例之间的元数据共享和分布式场景下状态协调的能力。它能够提供计算能力水平扩展和高可用等分布式系统必备的能力,集群环境需要通过独立部署的注册中心来存储元数据和协调节点状态。在生产环境建议使用集群模式。

生产环境建议使用集群模式部署,集群模式部署推荐使用 ZooKeeper 注册中心。

部署方式

ShardingSphere‐JDBC 独立部署

ShardingSphere‐Proxy 独立部署

混合部署架构

​ ShardingSphere‐JDBC 采用无中心化架构,与应用程序共享资源,适用于 Java 开发的高性能的轻量级OLTP 应用;ShardingSphere‐Proxy 提供静态入口以及异构语言的支持,独立于应用程序部署,适用于OLAP 应用以及对分片数据库进行管理和运维的场景。Apache ShardingSphere 是多接入端共同组成的生态圈。通过混合使用 ShardingSphere‐JDBC 和ShardingSphere‐Proxy,并采用同一注册中心统一配置分片策略,能够灵活的搭建适用于各种场景的应用系统,使得架构师更加自由地调整适合于当前业务的最佳系统架构。

image-20221229101656657

ShardingSphere‐JDBC

配置是 ShardingSphere‐JDBC 中唯一与应用开发者交互的模块,通过它可以快速清晰的理解ShardingSphere‐JDBC 所提供的功能。

数据分片

水平分库

水平分表

垂直分库

垂直分表

分片算法

分片算法 ShardingAlgorithm 已知实现

配置标识 自动分片算法 详细说明 类名
MOD Y 基于取模的分片算法 ModShardingAlgorithm
HASH_MOD Y 基于哈希取模的分片算法 HashModShardingAlgorithm
BOUNDARY_RANGE Y 基于分片边界的范围分片算法 BoundaryBasedRangeShardingAlgorithm
VOLUME_RANGE Y 基于分片容量的范围分片算法 VolumeBasedRangeShardingAlgorithm
AUTO_INTERVAL Y 基于可变时间范围的分片算法 AutoIntervalShardingAlgorithm
INTERVAL N 基于固定时间范围的分片算法 IntervalShardingAlgorithm
CLASS_BASED N 基于自定义类的分片算法 ClassBasedShardingAlgorithm
INLINE N 基于行表达式的分片算法 InlineShardingAlgorithm
COMPLEX_INLINE N 基于行表达式的复合分片算法 ComplexInlineShardingAlgorithm
HINT_INLINE N 基于行表达式的 Hint 分片算法 HintInlineShardingAlgorithm
COSID_MOD N 基于 CosId 的取模分片算法 CosIdModShardingAlgorithm
COSID_INTERVAL N 基于 CosId 的固定时间范围的分片算法 CosIdIntervalShardingAlgorithm
COSID_INTERVAL_SNOWFLAKE N 基于 CosId 的雪花ID固定时间范围的分片算法 CosIdSnowflakeIntervalShardingAlgorithm

分布式主键生成算法

分布式主键生成算法KeyGenerateAlgorithm已知实现

配置标识 详细说明 类名
SNOWFLAKE 基于雪花算法的分布式主键生成算法 SnowflakeKeyGenerateAlgorithm
UUID 基于 UUID 的分布式主键生成算法 UUIDKeyGenerateAlgorithm
NANOID 基于 NanoId 的分布式主键生成算法 NanoIdKeyGenerateAlgorithm
COSID 基于 CosId 的分布式主键生成算法 CosIdKeyGenerateAlgorithm
COSID_SNOWFLAKE 基于 CosId 的雪花算法分布式主键生成算法 CosIdSnowflakeKeyGenerateAlgorithm

时间服务

获取当前时间进行路由

  • 从数据库中获取当前时间进行路由
  • 从应用系统时间中获取当前时间进行路由

分片审计算法

分片审计算法 ShardingAuditAlgorithm 已知实现

配置标识 详细说明 类名
DML_SHARDING_CONDITIONS 禁止不带分片键的DML审计算法 DMLShardingConditionsShardingAuditAlgorithm

分片条件生成引擎

分片条件生成引擎

配置标识 详细说明 类名
DefaultShardingConditionEngine 默认分片条件生成引擎 DefaultShardingConditionEngine

读写分离

读库负载均衡算法

轮询

随机

加权轮询

高可用

数据库发现提供算法

MySQL.MGR GR基 于MySQL MGR 的数 据 库发现算法

MySQL.NORMAL_REPLICATION 基于MySQL主从同步的 数据库发现算法

使用限制

支持项

  • MySQL MGR 单主模式。
  • MySQL 主从复制模式。
  • openGauss 主从复制模式。

不支持项

  • MySQL MGR 多主模式。

分布式事务

​ 首先明确一点,分布式事务是比较麻烦的事情,如果系统可以通过本地事务的方式解决问题,最好先采用本地事务。如果要采用分布式事务,则需要事先明确一点:分布式事务中没有一揽子包治百病的解决办法,因地制宜选择合适的事务处理方案才是有效的做法。

ShardingSphere 提供了三种模式的分布式事务:

  • LOCAL
  • XA:基于 XA 协议的两阶段事务
  • BASE:基于 Seata 的柔性事务
LOCAL XA BASE
业务改造 需要 seata server
一致性 不支持 支持 最终一致
隔离性 不支持 支持 业务方保证
并发性能 无影响 严重衰退 略微衰退
适合场景 业务方处理不一致 短事务 & 低并发 长事务 & 高并发

Narayana

​ Narayana是一个开源的 JTA事务管理器实现,目前由 JBoss支持。你可以使用spring-boot-starter-jta-narayana starter添加合适的Narayana依赖

流量治理

可观测性

Prometheus

Jaeger

Logging

README

作者:银法王

记录:

 2022-09-10 第一次修订

参考:

​ ShardingSphere 官方文档


分布式数据库中间件ShardingSphere
http://jackpot-lang.online/2023/03/20/数据库/分布式数据库中间件ShardingSphere/
作者
Jackpot
发布于
2023年3月20日
许可协议