TaurusDB是一种基于MySQL的计算与存储分离架构的云原生数据库,一个集群中包含多个存储几点,每一个存储节点包含多块磁盘,每块磁盘对应一个或者多个slicestore的内存逻辑结构来管理. 在taurus的slicestore中将数据划为多个slice进行管理,每一个slice的大小是10G,Taurus架构图以下:算法
TauruDB的存储层支持append-only写和随机读,最小数据存储逻辑单元为plog,每一个slice中包含多个plog,默认每一个plog的大小为64M。slice中的plog主要用来存放page。Plog中存放中不一样版本的page,有些老page已通过期,须要删除;有些page是新page,须要被保留下来。数据库
Compator主要用来清理plog中过时的page,把一个plog上全部没有过时的page搬移到一个新plog,老的plog删除掉。架构
Compactor的任务须要频繁访问内存中索引结构和读写plog中的page页,这两部分都属于整个系统中关键资源,锁竞争的压力比较大,会直接影响性能,因此compactor的优化方案主要围绕减小内存访问和磁盘IO,须要考虑如下几个点:app
A、 选取的清理的plog集最优问题,每次回收须要搬运有效page,搬运的有效page数越少,磁盘IO就越小。如何每次调度都选取到垃圾量最大的一批plog;性能
B、 垃圾量是否分布均匀,如何让垃圾集中到一块儿,回收垃圾集中的plog,提升回收效率;测试
C、 回收周期是固定的,怎么样保证在每一个周期内,都能取到最优plog集。优化
当前,咱们提出了几个能够有效减小page搬运数,从而达到减小IO目的的方案。线程
关键点1:全局调度设计
全局调度的方案增大plog垃圾量的排序范围,从slice的范围增大到slicestore的范围。由于考虑到后面须要针对单个磁盘进行“加速回收”,因此不扩大到一个存储节点的全局范围。blog
全局调度方案按照slicestore来选取回收plog,先遍历全部的slicestore,而后在slicestore内部进行垃圾量排序,选取最多的若干个plog进行回收;
优势:有效避免一个slicestore中因为垃圾分布不均匀引发的plog的无效搬运,减小对plog的读写产生的IO;
缺点:排序范围增大后,排序算法会增长CPU的消耗;
关键点2:排序算法优化
原始方案中在slice内部对plog按照垃圾量排序采用C++标准库排序(std::sort),该算法内部基于快速排序、插入排序和堆排序实现。原始方案中每一个slice中最多存有160个plog,小数据量的排序或许效率影响不大,可是一个slicestore中存储成百上千的slice,排序算法的效率问题就值得关注。
Taurus设计了一种topN算法,可以提高该场景下的效率。假设须要在n个元素中选取m个最大的元素,两种算法的时间复杂度和空间复杂度:
C++标准库排序时间复杂度为O(nlogn),空间复杂度为O(nlogn);
topN算法排序时间复杂度为O(nlogm),空间复杂度为O(1);
Compactor应用场景中,n和m相差几个数量级,topN算法在时间和空间上都更具优点。
优势:减小时间复杂度和空间复杂度;
关键点3:调度数优化
公共线程池分配给compactor的线程数是固定的,每一个周期调度器生成一次任务。原始方案中compactor的每次生成的任务数由slice个数决定,会致使任务队列中的任务数过多或者过少。过多的话会失去时效性,也就是说plog的垃圾量会随着时间改变,若是在队列等待执行的时间太长,可能就不是当前最高垃圾量的plog,同时一次挑选的plog个数太多,会增长算法的时间和空间复杂度;过少的话,compactor线程没有跑满,会致使垃圾回收速度下降。
调度数优化也是基于全局调度优化,调度策略只须要保证在一个调度周期内,任务队列中任务数恰好知足compactor线程执行。假设有8个slicestore,分配了24个执行线程,每一个线程每一个调度周期完成一个plog的回收,则每一个调度周期每一个slicestore只须要生成3个任务。
调度数优化即记录公共线程池中正在执行和准备执行的任务数,跟据记录决定本轮调度生成多少个回收任务,从而保证执行线程恰好够用,且很少很多。
优势:保证垃圾回收速度,最优回收的plog集,有效的减小page的搬运量。
关键点4:冷热分区优化
在数据库系统中,数据的更新并非相同频率,一些数据页更新或者写入会更加频繁(例如系统页),这部分页面被称做热页,另一些更新不频繁的称做冷页。若是把冷页和热页混合放到一块儿,就会致使更高的写放大。举个简单的例子,假设有100个热页和10个冷页,冷页基本不更新可是每次垃圾回收,都须要重复把冷页搬运一次。若是把冷页单独写入一个plog,那么在垃圾回收阶段,就能够减小重复搬运这部分冷页,达到减小IO放大的效果。
优势:提升垃圾回收的效率和速度。
缺点:须要额外的内存记录热度信息。
关键点5:磁盘逃生优化
为了后台线程好比备份、快照、垃圾回收、页面回放等线程有足够的磁盘空间运行,在磁盘容量使用到达必定阈值,会置Full标志位,同时中止前台IO。在极端状况下,磁盘使用到阈值前台IO会出现断崖式下跌为零:
为了不在磁盘容量达到必定阈值以后前台IO彻底中止,在磁盘使用率未达到阈值时,就应该有相应的处理机制。好比说在磁盘使用率未达阈值时,增长以下处理:
A、 下降前台IO,减小磁盘的压力;
B、 加速垃圾回收,也就是TaurusDB中的compactor机制;
A点不涉及compactor的功能,因此本文先不涉及,下面主要介绍两种加速机制:
1、修改写IO优先级
Compactor做为后台线程,考虑到整个系统的效率,正常运行时plog写IO优先级默认为low。在加速回收阶段,plog的IO须要修改成high。
2、提升执行速度
前文可知,公共线程池为compactor分配固定数目执行线程,并且运行过程当中只支持扩容不支持恢复。若是压缩其余后台任务的执行线程,对整个系统的影响太大,量也不易控制。因此不考虑。
考虑到过程当中不能扩容,那就初始化就扩容,经过控制调度任务数控制任务执行速度。例如,假设compactor的运行线程在正常场景下为4个,加速状态下须要增长到8个。能够在公共线程池中先分配8个线程,在正常场景下,控制任务队列为4个,另外4个线程处于wait状态,只会占用文件句柄,并不影响CPU。而在加速状态下,控制任务队列中的任务数为8,就能够实现上述的加速逻辑。
因此,提高写IO的优先级可以加速page的搬运,提高垃圾回收速度。经过控制调度任务数控制任务执行速度却很难控制很精准,上下会有必定的小波动。
以上提到的垃圾回收compactor优化方案中,磁盘逃生优化可以处理磁盘容量紧急状况。目前根据本地测试,在500G的小数据集状况下,IO放大能减小到原来的1/6。系统资源占用减小到原来的1/3。
点击这里,了解更多精彩内容