zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

MYSQL POLARDB 学习系列之 拆解 POLARDB 6 Auto-Scaling 与性能优化 (翻译)

2023-02-18 16:23:52 时间

,最近问 POLARDB 的同学同学是越来越多,准备开一个群,专门和大家一起学习 POLARDB for MYSQL 的数据库相关知识和PG ,MYSQL等数据库,分享相关的经验,和大家相互学习。

如果敢兴趣可以加 liuaustin3 微信,加到polardb 的知识分享群和文章问题询问群,如果可能还会拉上polardb的厂商的一些工作者,(争取,需要征得人家的同意) 来更好的学习POLARDB for MYSQL 。 同时最近问问题的人也比较多,此群也可以提出对文章中的问题使用。

——————————————————————————————

接上期,本期主要是针对POLARDB 的扩展性和性能优化进行翻译。

Auto-Scaling

对于serverless的数据库本身应有一种能力,一种在扩展时对于用户无感知的无缝透明扩展的能力。在理想的状态下,即使当数据库重启或者跨节点迁移的过程中,应用也不应该感知到任何异常,甚至像数据库无法连接,事务被终止,或者长时间的没有响应的状态下,也能具备此项能力。

在POALRDB SERVERLESS ,当切换发生时,代理节点有责任来Hold 住客户的连接不报错。他停止活跃的事务并且停止转发后续的事务的语句到老的RW 节点。同时等待老的RW节点完成已经发送的事务(举例100ms),在此以后老的节点刷新所有的脏页到shared memory 然后关闭。于此同时新的RW将加载shared memory 并且初始化新的RW 节点的local memory的状态(扫描undo header 去建立活跃的事务列表)。最后代理连接到新的RW节点,恢复他的session 状态,恢复转发过来的语句的状态。而一些大型的事务这些语句在老的RW节点也没有完成,所以必然的在新的节点上他们将开始回滚。

对于多语句的大事务本身如bulk 插入,代理还可以跟踪每个语句的savepoint, savepoint表示事务的执行进度,即事务开始以来的第i条语句。因此,当切换事件发生时,代理可以通知新的RW节点从最近的保存点恢复执行,这避免了回滚整个事务,并显著提高了迁移的透明度。

(个人认为能做到上面所说的问题,并且能做到,在各种数据库中,包含分布式系统,都是非常不容易的一件事情)

回想一下,在切换过程中,活动事务需要暂停,直到新的RW节点接管服务。因此,缩短暂停是至关重要的。在PolarDB Serverless中,通过共享内存传输事务状态(例如脏页和回滚段)比依赖远程存储的传统方式更快,另外其他的优化方法,如语句级别的回滚对以上的问题也是有帮助的。

总的来说,系统可以将暂停的时间降低到2-3秒,计划在未来的工作中研究更多的优化的方法,如将事务的锁放入到shared memory 来支持多RW节点,并且shared memory 中缓存中间结果,并加速恢复后的查询快速恢复。

Performance optimizations

在系统的设计中,一些架构的负面的因素,会影响系统的性能,如数据库的访问可能会来自与远程的remote memroy 节点或者存储节点,这可能设计明显的网络延迟,对于这些问题,我们进行了一些列的优化和改变。

4.1 optimistic locking

在3.2 的章节中,我们讨论了,RO 节点在从根节点到叶子节点通过 coupling 协议来获取PL锁来管理页面的方式,即使RW同时进行SMO,RO 节点实际上仍然能看到B+树上的一致性物理的结构,尽管在大多数的情况下,获取PL是完全通过 RDMA CAS 来进行的快速搜寻的,但是实际上可能还是会进行多轮的来回信息的沟通。

这里我们进行一个假设,一个乐观的假设,RO 节点将不会再根节点到叶子节点传输时遇到SMO的情况,所以我们不需要获得任何PL锁。当SMO 被发现的时候可以进行重试或触发悲观方式的信息处理方式。SMO 可以进行检测,如一个SMO 的计数器在RW上维护,当在B树中SMO 发生的时候,计数器加 1 同时RW将快照中SMO 修改的记录应用到SMO 发生的所有的页面上,在每次查询的开始,SMO 计数器的快照作为SMO query 中的结果,当RO 节点执行查询从根到叶子进行遍历的情况下,如果发现路径上任何页面的SMO TREE 都大于 SMO QUERY 的页面,这就说明在查询期间进行了SMO,所以读取的页面就可能有误了。

注解:什么是SMO ,SMO 是 structure Modification Operations , 其实就是我们俗称的DDL。

4.2 index -Awared Prefetching

在操作系统和存储系统部分系统已经可以开始进行数据预取的工作,但对于数据库的预取技术还是一个未知数,然而对于在POLARDB 中的核心对于SQL的执行计划中可以做的是通过准确得预期对于将要访问的下一个数据块进行预先的获取。在POLARDB SERVERLESS ,我们通过 batched key prepare , BKP 页面通过在内存和存储系统中预取去避免远程IO中的数据获取延迟。

类似的预取技术方法也用于hash join 去避免CPU 缓存的命中失效的问题,这里有大量的日常的数据库操作通过访问二级索引来完成。

如 select name, address ,mail, from employee where age > 17

在这里例子中,字段 age 有一个二级索引,但是其他的如name ,address mail 字段必须从主键的索引中获取数据,当MYSQL 执行了这句话,典型的第一个过程是扫描二级索引,并从中获取主键的信息,然后在去读所需要的数据,第一步是一个顺序性的访问加速预读B+TREE的叶子节点,第二步是随即的访问这里我们就要石红BKP的方式来进行优化了。

当部署的BKP的在我们的存储引擎,BKP的接口将接受一组键,去预先加载,当接口被调用,引擎将开始在后台开始预取的任务,从这些目标的二级索引中来加载相关的页面从远程的内存或存储中。

BKP 同时也可以优化分析工作负载,通过TPC-H 查询,举例很多JOIN 的工作尤其是通过INDEX来进行的等值的JOIN,尤其是一些大型的表,当处理到这些大表或者表中有冷数据的情况下,大量PAGE将可能被提取,BKP通常将加速等值的JOIN 通过索引来访问表,在MYSQL 这里有一个JOIN BUFFER 能够加速left join产生的累积的列值,早期连接中的表被分批读入连接缓冲区,当连接缓冲区中的行数达到阈值时,BKP将构建并发送一批键到存储引擎,以预取内部表的页面。同时,存储引擎在后台预取包含这些键的页面。当连接缓冲区已满时,缓冲区中的行将与内部表连接,我们预计所需的大多数页面应该已经加载到缓存中。

翻译到这里,已经是POLARDB 的 PolarDB Serverless: A Cloud Native Database for Disaggregated Data Centers 的第六期了,翻译已经接近尾声了,剩下第七期将翻译最后一部分与数据库的恢复 包含内存节点恢复,数据节点恢复有关的内容。

对于POLARDB 的学习在我目前的工作计划将一个长期的工作,我们目前已经掌握了POLARDB FOR MYSQL的 一些与传统 MYSQL RDS 之间的工作的差异的特性,性能方面的差异点,后期可能我们TEAM 还将对POLARDB 进行一些测试,如不同的配置的POLARDB 在性能上的差异,彻底将POLARDB FOR MYSQL 在使用和推荐公司内部的项目使用弄的通透。

另外一个数据库如果想发展的更快,需要OPEN ,否则我们可以看看 DB2 ,Informix ,等这样的数据库,由于使用面积小,获得的使用业态少,都在濒临停滞和没有声音的状态,希望POLARDB 能尽快开放的方式,让更多的业态使用,保持新鲜度,持久度。