数据拆分原理如下图所示:计算扩展性
无论是水平拆分还是垂直拆分,PolarDB-X常常碰到需要对远超单机容量数据进行复杂计算的需求,例如需要执行多表JOIN、多层嵌套子查询、Grouping、Sorting、Aggregation等组合的SQL操作语句。
针对这类在线数据库上复杂SQL的处理, PolarDB-X额外扩展了单机并行处理器(Symmetric Multi-Processingy,简称SMP)和多机并行处理器(DAG)。前者完全集成在PolarDB-X内核中;而对于后者,PolarDB-X构建了一个计算集群,能够在运行时动态获取执行计划并进行分布式计算,通过增加节点提升计算能力。
平滑扩容
PolarDB-X扩容通过增加RDS/MySQL实例数,将原有的分库迁移到新的RDS/MySQL实例上,达到扩容的目标。PolarDB-X采用基于存储计算分离的Shared-Nothing架构,最大限度地发挥了云数据库的弹性扩展能力。
PolarDB-X的架构图如下:如上图所示,PolarDB-X整个架构核心可分为3个部分: GMS(Global Meta Service):负责管理分布式下库、表、列、分区等的元数据,以及提供TSO服务; CN(Compute Node):负责提供分布式的SQL引擎与强一致事务引擎; DN(Data Node):提供数据存储服务,负责存储数据与副本数据的强一致复制。
PolarDB-X存储层使用的是X-DB。因此,每一个DN节点就是一个X-DB实例(X-DB的介绍请看这里)。X-DB是在MySQL的基础之上基于X-Paxos打造的具备跨可用区跨地域容灾的高可用数据库,使用InnoDB存储引擎并完全兼容MySQL语法,它能提供Schema级别的多点写与Paxos Group的Leader调度的能力。PolarDB-X的分区副本的高可用与故障容灾就是建立在X-DB基础上的。
PolarDB-X扩容原理步骤如下:
- 创建扩容计划选择新增加RDS/MySQL,并选定需要迁移到新RDS/MySQL实例上的分库,提交任务后系统自动在目标RDS/MySQL上创建数据库和账号,并提交任务进行数据迁移同步。
- 全量迁移系统选择当前时间之前的一个时间点,将这个时间点之前的数据进行全量的数据复制迁移。
- 增量数据同步完成全量迁移后,基于全量迁移开始之前时间点的增量变更日志进行增量同步,最终原分库和目标分库数据实时同步。
- 数据校验增量达到准实时同步后,系统自动做全数据校验,并且订正因为同步延迟造成的不一致数据。
- 应用停写和路由切换校验完成后,并且增量依然维持准实时同步,业务选定时间进行切换,为确保数据严格一致,建议应用停服(也可以不停,但可能面临同一条数据高并发写入覆盖问题),引擎层进行分库规则的路由切换,将后续流量转向新库,切换过程秒级完成。
扩容示意图下:为了保证数据本身的安全,便于扩容回滚,在路由规则切换完成后,数据同步依然会运行,直到数据运维人员确认服务正常后在控制台主动发起旧分库数据的清理。
整个扩容过程对上层的业务正常服务几乎没有影响(如果RDS/MySQL实例规格过小或者压力过大则可能造成部分影响),切换时如果应用不停服,建议操作选择在数据库访问低谷期进行,降低同一条数据并发更新覆盖的概率。
读写分离
PolarDB-X的读写分离功能是基于RDS/MySQL只读实例所做的一种相对透明读流量切换策略。当PolarDB-X存储资源MySQL主实例的读请求较多、读压力比较大时,您可以通过读写分离功能对读流量进行分流,减轻存储层的读压力。
业务应用在能够忍受只读实例相对于主实例数据同步延迟的前提下,不需要修改代码,即可在PolarDB-X控制台中增加RDS/MySQL只读实例和调整读权重,将读流量按照需要的比例在RDS/MySQL主实例与多个RDS/MySQL只读实例之间调整,写操作和事务操作则统一走RDS/MySQL主实例。需要注意的是,主RDS/MySQL实例和只读RDS/MySQL存在数据同步延迟,并且在发生大的DDL或者数据订正时,有可能导致分钟级别以上的延迟,所以需要业务忍受该情况所带来的影响。添加只读实例可以使读性能线性提升。例如在初始有一个只读实例的情况下,挂载一个只读实例,读性能提升至原来两倍,挂载2个只读实例,则读性能为单个主库读性能的三倍。
读写分离流量分配与扩展
PolarDB-X读写分离功能采用了对应用透明的设计。在不修改应用程序任何代码的情况下,只需在控制台中调整读权重,即可实现将读流量按自定义的权重比例在存储资源MySQL/RDS主实例与多个存储资源只读实例之间进行分流,而写流量则不做分流全部到指向主实例。
添加只读实例可以使读性能线性提升。例如在初始有一个只读实例的情况下,挂载一个只读实例,读性能提升至原来2倍,挂载2个只读实例为单个主库的3倍。设置读写分离后,从存储资源MySQL主实例读取属于强读(即实时强一致读);而只读实例上的数据是从主实例上异步复制而来存在毫秒级的延迟,因此从只读实例读取属于弱读(即非强一致性读)。您可以通过Hint指定那些需要保证实时性和强一致性的读SQL到主实例上执行。示意图如下:
读写分离对事务的支持
读写分离仅对显式事务(即需要显式提交或回滚的事务)以外的读请求(即查询请求)有效,写请求和显式事务中的读请求(包括只读事务)均在主实例中执行,不会被分流到只读实例。
常见的读、写请求SQL语句包括:
- 读请求:SELECT、SHOW、EXPLAIN、DESCRIBE。
- 写请求:INSERT、REPLACE、UPDATE、DELETE、CALL。
非拆分模式的读写分离
PolarDB-X的读写分离可以在非拆分模式下独立使用。
PolarDB-X控制台上创建PolarDB-X数据库时,在选定一个数据库实例的情况下,可以选择将底层数据库实例下的一个逻辑数据库直接引入PolarDB-X做读写分离,不需要做数据迁移。
分布式事务
分布式事务通常使用二阶段提交来保证事务的原子性(Atomicity)和一致性(Consistency)。
二阶段事务会将事务分为以下两个阶段:
- 准备(PREPARE)阶段:在PREPARE阶段,数据节点会准备好所有事务提交所需的资源(例如加锁、写日志等)。
- 提交(COMMIT)阶段:在COMMIT阶段,各个数据节点才会真正提交事务。
当提交一个分布式事务时,PolarDB-X服务器会作为事务管理器的角色,等待所有数据节点(MySQL服务器)PREPARE成功,之后再向各个数据节点发送COMMIT请求。
全局二级索引
全局二级索引(Global Secondary Index,GSI)支持按需增加拆分维度,提供全局唯一约束。每个GSI对应一张索引表,使用XA多写保证主表和索引表之间数据强一致。
全局二级索引支持如下功能:
- 增加拆分维度。
- 支持全局唯一索引。
- XA多写,保证主表与索引表数据强一致。
- 支持覆盖列,减少回表操作,避免额外开销。
- Online Schema Change,添加GSI不锁主表。
- 支持通过HINT指定索引,自动判断是否需要回表。