共计 5724 个字符,预计需要花费 15 分钟才能阅读完成。
简介:在刚刚公布的 PolarDB-X 2.1.0 版本中,开源了通明分布式能力,能带给用户齐全不同的通明分布式数据库应用体验。其中,一个最显著的不同,就是用户不再须要关注分区健这个概念,这也是副标题《再见,分区健》的来由。
事务、全局索引、通明分布式
再见,分区健!
——陈默(墨城)
阿里云数据库技术专家
理解更多 PolarDB-X 内容:https://developer.aliyun.com/…
在刚刚公布的 PolarDB-X 2.1.0 版本中,开源了通明分布式能力,能带给用户齐全不同的通明分布式数据库应用体验。其中,一个最显著的不同,就是用户不再须要关注分区健这个概念,这也是副标题《再见,分区健》的来由。
一、从“分区”开始
image.png
1970 年代末,分区的概念首先在并行数据库系统中呈现,用来代表一组记录的汇合。在并行数据库中,表首先依照某种规定被切分为若干分区,每个分区存入数据库节点,每个数据库节点都有独立的 CPU 内存和存储节点,节点通过网络替换数据。因为没有共享应硬件资源,该构造也被称为 shared-nothing 架构。
引入分区和 shared-nothing 架构,是为了通过减少节点的形式来晋升存储和计算能力,也称为程度扩大。
从程度扩大的角度登程,用户必定心愿尽可能平均地将数据扩散到各个分区中,比方随机调配。但这会导致查问时须要扫描全副分片,性能上无奈承受。而可行的方法是依照某些列的值来确定一行数据应该落在哪个分片,这些用来确定一行数据应该落在哪个分片的列,就是分区键。
image.png
2000 年当前,随着互联网的遍及,须要解决的数据量越来越大,超过了单机零碎可能承载的容量下限,分区 + shared-nothing 带来的程度扩大能力从新受到重视。
这一阶段的实现大抵能够分为两类:
第一类是 NoSQL 零碎,通常是从零开始实现的全新零碎,强调高可用和可扩展性。引入分区之后,因为事务和 SQL 的执行代价升高,通常这些零碎不反对跨行事务和 SQL 接口,因而也被称为 NoSQL 零碎。代表性的实现有 Google 的 BigTable 和 Amazon 的 Dynamo。
第二类是中间件。通过在零碎和单机数据库之间减少中间层,将查问申请路由到数据所在的数据库节点。这类零碎通常不反对跨分片事务和全局索引,反对 SQL 接口,但要求 SQL 语句中必须蕴含分区键上的条件。
整体上看,这一阶段数据库将重心放在了解决高可用和扩展性问题上,代价是放弃了对事务和 SQL 的反对。从开发人员的角度来看,最直观的感触是设计业务逻辑时须要思考分区键如何抉择。
image.png
然而,开发者真的违心设计分区键吗?开发者真的能设计分区键吗?如果零碎有数十甚至上百张表,又该怎么做?除此之外,短少分布式事务也不合乎很多用户的应用习惯。
Google 在论文中总结道,许多工程师将过多精力放在解决数据一致性上,本来封装在数据库外部的逻辑溢出到利用代码中,大幅提高了利用代码的复杂度。因而,不反对分布式事务和要求开发者抉择分区键是应用分布式数据库最次要的阻碍。
接下来,一起看看 PolarDB-X 在反对分布式事务中应用的关键技术,全局索引如何晋升查问性能、以及如何为用户提供无需关注分区健的通明分布式体验。
二、分布式事务
image.png
数据库系统须要面对各种各样的简单状况,硬件故障可能导致系统在写入数据的任何阶段解体,比方利用零碎可能在一系列间断操作中忽然退出,多个客户端可能并发地批改同一条记录等。
出现异常时,数据库须要提供可靠性保障,而事务就是对可靠性保障的简化形容。事务是一系列读写操作的汇合,对读写操作系统提供四个方面的保障:
① 原子性:如果出现异常,用户能够通过重试事务来解决,无需放心失败的事务对数据产生影响。
② 一致性:用户无需放心数据操作会违反束缚定义,比方惟一束缚外键等。
③ 隔离性:用户能够认为只有本人在操作数据库,无需放心多个客户端并发读写雷同的数据会产生异样。
④ 持久性:一旦事务提交胜利,用户就无需放心事务产生的变更会因为其余异样而失落。
分布式事务中因为存在多个分区,原子性和隔离性受到影响。
对于原子性,须要协调所有分区在提交阶段的行为,保障一起提交或一起回滚。业界通常应用两阶段提交协定来解决此问题。常见的实现有 Percolator 和 XA 协定。Percolator 在提交阶段提早较高,只在提交阶段汇报抵触谬误,且仅反对乐观锁场景,与传统的关系数型数据库基于乐观事务的模型有较大区别。因而 PolarDB-X 抉择通过 XA 协定反对两阶段提交。
对于隔离性,要求可能对不同分区上产生的单分区事务进行全局排序。业界常见的实现办法有基于 GTM 和 TSO 两种实现。GTM 计划过于依赖中心化的事务管理器,容易呈现零碎瓶颈。因而 PolarDB-X 抉择通过基于 TSO 的 MVCC 计划来实现隔离性。
image.png
上图为分布式事务具体的执行过程。
启动事务后,首先向 TSO 获取一个 star_ts,作为读取的快照,接管并解决用户申请。过程中依据数据对应的事务状态、快照工夫戳和数据提交工夫戳来判断数据是否可见,以保障隔离性。在提交过程中,CN 节点先告诉所有参加写操作的分区执行 prepare,记录事务状态,最初告诉所有参与者 commit。在记录事务状态胜利之前产生的异样都会导致事务退出,以此保障原子性。
采纳 2PC 和 TSO + MVCC 计划实现的分布式事务常常被质疑的问题是提交阶段提早减少和 TSO 单点问题。
针对上述两个问题,PolarDB-X 都进行了工程上的实现优化。
image.png
两阶段提交因为减少了 prepare 阶段,提早高于单分片事务。实际上,对于单分片写多分片读的事务,无论读取是否跨分区,仍然能够应用一阶段提交来保障原子性。PolarDB-X 反对自动识别此类情况,可能显著缩小这类场景下的提交提早。
image.png
TSO 计划采纳单点授时,潜在问题是存在单点故障和单点性能瓶颈。PolarDB-X 的 GMS 服务部署在三节点集群上,通过 X-Paxos 协定保障服务高可用。同时对多种场景进行了优化,使得带分区条件的点查、点写可不依赖 GMS , 晋升查问性能的同时也升高了 GMS 的压力。
另外,单个 CN 过程默认采纳 grouping 的形式,将同一时间产生的多个 TSO 申请合并为 batch 操作一次性获取,进一步保障 GMS 不会成为零碎瓶颈。
上面通过 Flashback Query 示例来展现 MVCC 带来的非凡能力。
三、全局索引
image.png
上图为一张依照主键拆分的表,t1 表 partition by Hash(ID)。当提供的查问条件是 id 上的等值查问时,比方 id=14,算出 14 的分区哈希值之后,即可疾速定位到 p3 分片。
然而如果依照 name 进行查问应该怎么解决?如果只能全分片扫描,代价过大,不可承受。为了找到答案,先看单机数据库如何解决此问题。
image.png
在 MySQL 中,同样的表构造是一棵 B+ 树,依照主键 id 有序。当以 id 为条件进行查问时,数据库会在 B+ 树上做二分查找,从而疾速定位到数据所在叶子节点。同样当以 name 为条件进行查问时,则无奈进行二分查找,只能将整棵 B+ 树都进行遍历,即全表扫描,代价较高。
image.png
在 MySQL 中,为了防止全表扫描,会在 name 上创立二级索引,即创立了另一棵 B+ 树,依照索引列有序,此处为依照 name 列有序,其叶子节点记录了 name 对齐以及其对应的主键 id。对于 name 上的等值查问,数据库会先在二级索引的 B+ 树上进行二分查找,找到对应的 id 之后再应用此 id 在主键 B+ 树上进行查找,即回表操作。
二级索引的理念在计算机中十分常见,其本质是用空间换工夫。在 MySQL 中设计主键更多的是思考其业务上的唯一性,而不在意某列是否为查问应用最多的列,背地的起因是创立二级索引的老本非常低。
image.png
分布式数据库中,依照主键分区后如何进行 name 列查问,同时还能防止全表扫描?参考空间换工夫的思路,以 name 为分区键,再将数据做一份冗余,将 name 映射到 id,这份冗余的数据称为全局二级索引。
如上图所示,依照 name=Megan 做查问时,先通过全局二级索引定位到 Megan 所在分片,找到 Megan 的 id 值,用 id 值到主表上查问整条记录所在的分区,此过程也称为回表。
那么,如果在分布式数据库上创立全局二级索引可能像在单机数据库上一样不便,则无须再关注分区键。因而,要害就在于全局二级索引。全局索引要尽可能地做到与单机数据库一样的兼容性,兼容度越高就越通明,开发者就可能应用单机数据库的教训来应用分布式数据库。此处兼容性体现在很多方面,包含一致性、创立形式、应用形式和兼容其余 DDL。
image.png
首先是数据的一致性。PolarDB-X 反对强统一事务,通过事务来保障主表和索引表的数据统一,所有对蕴含索引表的表进行写入的操作都会默认包装在强统一的分布式事务中。
image.png
分布式数据库中,实现 Online Schema Change 须要面临的次要挑战是:schema 变更过程中,不同的 CN 节点上,不同事务看到的元数据版本并不统一。
单机据数据库解决此问题的方法是通过对元数据加锁,保障任意时刻所有事务都只能看到同一版本的元数据。但分布式系统中,因为网络提早存在不确定性,跨节点实现加锁可能导致显著的读写卡顿,因而并不合乎 online 的定义。
PolarDB-X 参考了 Google F1 实现的 Online Asynchronous Schema Change,通过减少两个相互兼容的中间状态,容许零碎中同时存在至少两个元数据版本,使得 DDL 过程中无需加锁,不会阻塞任何读写申请。有了 Online Schema Change 的撑持,在 PolarDB-X 中应用 create index 语句即可轻松创立全局索引,无需依赖任何第三方组件。
image.png
在各种 DDL 操作中保护索引表数据统一,工作量很大。PolarDB-X 反对无锁化的 Online DDL,依据 DDL 类型能够主动抉择适合的执行形式,且能主动保护全局二级索引。
image.png
创立完索引后,如果须要手动指定 SQL 应用全局二级索引,也不是一种敌对的应用体验。正当的形式应该相似于单机数据库,由数据库主动抉择应用全局二级索引。
因为索引自身也是一张逻辑表,且回表操作能够了解为索引表和主表在主键上做 Join,能够复用大部分分区表上执行打算的代价预计逻辑,应用估算主表上的执行打算代价的逻辑来估算索引表上的执行打算代价。
难点在于,两个表做 Join,一个蕴含三个全局索引,而另一个没有全局索引,执行打算的空间有十分大差别,须要更简单的执行打算枚举算法以及性能更加强劲的 CBO 设计。
PolarDB-X 反对基于代价的优化器,能够主动实现索引抉择。
上面通过一个 Demo 来展现如何通过全局索引优化查问性能。
从下面演示能够看到,有了全局二级索引的反对,能够像应用单机数据库一样,建表时毋庸指定额定的拆分键,之后通过 MySQL 原生语法创立索引来晋升查问性能。
四、通明分布式
除了分布式事务和全局索引,分区算法的设计也是提供通明分布式体验的另一个要害。
image.png
单机数据库中,索引能够很好地反对前缀查问。而全局索引应该如何解这类问题?
创立多列索引时,PolarDB-X 会别离对每一列进行哈希,在匹配到前缀的状况下仍然能做肯定的分区裁剪。
image.png
在单机数据库中创立索引较为随便,比方在性别列上创立索引,索引的区分度较低,个别不会被应用,写入时也会有肯定争抢,但不会导致太大的问题;如果是分布式数据库,索引只有两个值,依照哈希进行分区,则只会散布在两个节点上。如果业务是以写入为主,则无论集群有多少台机器,最初瓶颈都在这两个节点上,也就失了分布式数据库扩展性的初衷。
因而全局索引肯定要解决 BigKey 问题,能力升高应用门槛。
image.png
PolarDB-X 通过将主键和索引 key 一起作为分区键,使得热点呈现时仍然可能依照主键进行进一步决裂,从而打消热点。
image.png
对于拆分算法和分区散布雷同的两张表或索引,PolarDB-X 反对将 Join 下推到存储节点上执行,在 OLTP 场景下能够显著升高网络开销,晋升查问性能。但如果不对分区操作进行限度,可能会因为分区的决裂合并或分区迁徙,导致两张表分区的散布变得不同,使得 Join 无奈下推。从用户角度看,可能是呈现了一些分区操作后反而导致查问执行性能降落,导致用户产生一些应用上的纳闷。
为了解决上述问题,PolarDB-X 在后盾引入了两个概念:Table Group 和 Partition Group。
image.png
Table Group 是一组 Global Index 的汇合,零碎会确保 Table Group 中的索引具备雷同的数据分布。当产生分区决裂合并时,Table Group 中的索引会一起进行决裂和合并,保障数量统一。
处于同一个 Table Group 中的 Global Index,雷同的分区会组成一个 Partition Group。PolarDB-X 会保障雷同 Partition Group 中的分区始终落在雷同的 DN 上,保障分区迁徙操作不会影响 Join 的下推。
image.png
正当布局 Table Group 能够升高分区迁徙等操作的代价。PolarDB-X 应用 Table Group 与 Partition Group 来对全局索引上的 Join 下推进行优化。
image.png
分区 + shared-nothing 架构带来了良好的可扩展性,但须要额定反对分布式事务和解决跨分区查问性能问题。PolarDB-X 的分布式事务基于 2PC 和 TSO+MVCC,通过 1PC 优化升高提交阶段的提早,通过 TSO 合并优化确保 GMS 不成为瓶颈。通明全局索引良好地兼容了单机数据库上的索引应用体验,显著晋升跨分区查问的性能。
PolarDB-X 以分布式事务和通明全局索引为外围的通明分布式技术,显著地升高用户应用分布式数据库的门槛。
原文链接:http://click.aliyun.com/m/100…
本文为阿里云原创内容,未经容许不得转载。