钉钉作为国内领先的企业IM工具,在中国有超过亿级别的用户。随着新型冠状病毒肺炎疫情的爆发,大量的企业员工选择了soho模式,企业办公协同工具的需求瞬间爆发。
钉钉作为中国企业办公IM的首选应用,不仅具有项目群、视频通话、视频会议、日报、打卡、远程投屏等基础能力,还具备深度、灵活订制各种 OA (Office Automation,办公室自动化) 应用的能力,极大方便了人与人之间的链接,可以帮助企业员工快速、高效地沟通和协作。
也因此,钉钉迅速冲上了AppStore免费榜的第一位。瞬间爆发的在线办公需求,导致钉钉的访问流量激增。每天早晨的打卡风暴,迅速增长的聊天信息,一次次的流量洪峰冲击着钉钉的业务后台。但是借助于阿里云提供的弹性基础设施,钉钉平稳的渡过了每一次的流量洪峰。
在亿级别的用户体量下,钉钉的消息系统,除了要保证消息及时正确地传递,还要保证已读/未读等特有功能。而且不同于市场上常见的用户级IM工具,企业IM需要实现聊天记录的永久保存,并且提供多端漫游功能。
在用户量持续爆炸性增长的前提下,聊天记录永久保存给钉钉业务带来极大的成本压力。同时在数据爆炸的前提下保证聊天记录的读写性能不降低也是一个极大的挑战。
面对这些挑战,钉钉业务选用了X-Engine作为全量钉钉消息的最终存储引擎,实现了性能和成本的平衡。而且在此次企业协同办公需求爆发期间,钉钉业务的数据库系统顶住了所有的流量洪峰。
1.为什么是X-Engine
在X-Engine诞生之前,钉钉采用的是InnoDB引擎。在用户爆发增长,面临存储的压力之后,钉钉考虑了多种候选方案,例如Hbase等nosql服务。但企业IM对数据一致性如事务等功能有比较苛刻的需求,同时业务类型的多样化,也对诸如二级索引等数据库的功能有比较强的依赖。
钉钉消息业务采用X-Engine之后,相同数据所需的磁盘空间比InnoDB引擎减少了62%,同时继续保留了对事务以及二级索引等数据库特性的支持。业务代码不做任何修改,即可以迁移到X-Engine集群上。
钉钉的聊天消息有着非常典型的时效性,即最近发送的消息会被经常访问,而历史的消息则很少被读取。X-Engine天然的冷热分离能力,确保了我们对最新的消息有着最高的处理能力,而对历史的消息有着最高的压缩比,这样的设计兼顾了性能和存储成本。
我们在著名的Link-Bench和阿里巴巴内部交易业务两个数据集上测试了X-Engine的存储空间效率。在测试中,对比开压缩的InnoDB引擎,X-Engine有着2倍空间优势,而对比未开压缩的InnoDB,X-Engine则有着3~5倍的优势。
2.X-Engine架构
在阐述为什么X-Engine可以节约这么多存储成本之前,我们先看看它的整体架构。
X-Engine采用了LSM-tree典型架构。在LSM-tree的数据组织下,写入的数据首先进入一个内存表中,对该部分数据的读写都是在内存中进行,因此访问最新的数据有着最高的效率。
在内存表的大小达到一定阈值之后,将会冻结进行转储,并持久化到磁盘上。X-Engine在磁盘上的数据也是分层的,随着时间的推移,compaction过程会根据数据的访问频度,将最冷的数据转移到LSM-tree的最底层并进行压缩。因此访问最少最冷的数据有着最长的访问路径,而温度稍高的数据访问路径更短。
数据分层的架构,让我们可以对不同的数据集采用不同的处理模型。例如对于新写入的数据,使用高度并发的事务流水线技术,这项技术可以提高极高的写入吞吐。而对于占整体数据量95%以上的底层数据,使用紧凑编码并进行压缩,以降低空间。而对于底层数据中散布的部分热点数据,则充分使用BlockCache和RowCache来加速读操作。
3.X-Engine如何有效降低成本
目前广泛使用的InnoDB引擎也是可以通过开启压缩来降低存储空间的,那为什么在钉钉IM的消息存储中,X-Engine有着更好的表现呢?因为X-Engine有以下几个独门秘籍:
3.1 紧凑的数据页格式
X-Engine的记录更新使用的是copy-on-write技术,避免原地更新数据页,新数据写入到新的数据页中。由于既有数据不可更新,可以紧凑存储只读数据页面,并使用前缀编码等数据压缩技术,提升页面空间的使用效率。已经失效的历史记录版本则由compaction过程负责清理,保证有效记录都紧凑排列。
Innodb引擎采用传统B+tree组织数据,每个page是一个节点。它在内存中会组织为一个内存堆。为保证插入和更新的效率,InnoDB的page大部分时候都不是全满状态。这种结构虽然有较好的内存原地更新性能,但是持久化到磁盘上,空间使用效率非常低下。
即使初始顺序批量灌入数据创建了紧凑的page结构,后续更新带来的分裂、合并依然会在page中引入缝隙,降低空间使用率。记录在InnoDB的page中的组织和X-Engine的DataBlock中的组织对比如下图所示,可以看到在InnoDB的page中存在大量空洞。
一个经常碰到的场景是:使用InnoDB引擎导入所有基础数据并开启压缩之后,空间表现非常优秀。但是运行一段时间,空间膨胀会非常厉害。这种特性对于数据库实例在不同机器上的弹性调度是非常不利的,而X-Engine则能保证非常稳定的空间占用。
除了LSM-tree带来的天然压缩优势之外,X-Engine团队也探索了其他的数据压缩技术,例如Extent级别的列存,这个可以进一步提升压缩效率到10倍以上。当然在如何在一个TP型存储引擎中,在提升存储效率的前提下保证读取性能是一个值得进一步探讨的话题。
3.2 数据压缩及无效记录清理
由于X-Engine的Data Block无需原地更新,经编码之后的数据页,可以使用通用压缩算法(zlib,zstd,snapy等)压缩。所有X-Engine实例中处在LSM-tree中低层次的数据都会默认压缩。
数据压缩是以计算资源换空间的技术,在Data Block的生成时需要消耗CPU资源进行压缩,被压缩的Data Block被访问到时,则需要消耗资源进行解压。因此选用一个压缩率高及压缩/解压速度快的压缩算法也非常关键。
经过大量对比测试,X-Engine默认选用了ZSTD压缩算法,但同时也保留了对其他算法的支持。除了使用压缩之外, compaction过程会对无效记录进行删除,只保留有效记录。compaction执行的越频繁,无效记录的占比越低,空间使用效率越高。因此保证合适的compaction频率也是提升空间使用效率的关键。
从某种删除无效记录的角度上看,compaciton和压缩一样,代表着一种以计算资源换空间的理念。为了应对compaction对计算资源的消耗,X-Engine团队研发了FPGA compaction技术,使用异构计算设备来加速compaction过程。
压缩是在compaction过程中同步进行的。我们FPAG 上实现compaction算子的同时,也实现了压缩算子,在一个FPGA硬件流水线内同时完成compaction+压缩操作。虽然FPGA价格不菲,但是经过评估,X-Engine异构计算加速技术能够提供更优异的成本效益比。更详细的数据可以查看论文FPGA-Accelerated Compactions for LSM-based Key-Value Store
压缩及compaction可以减少磁盘空间占用。而FPGA等异构计算设备算力的加持让我们可以不用付出性能的代价。即使在没有FPGA加速卡的机器上,借助合理的调度算法,X-Engine也能以较小的性能代价获得存储空间的节省。
3.3 智能冷热分离算法
虽然X-Engine有紧凑数据布局的优势, 有ZSTD这样高效的压缩算法,有FPGA提供的澎湃算力。但如何巧妙的利用好这些能力也是一个挑战。其中最核心的问题是保证访问更频繁的数据存储在LSM-tree架构中更高的层级,缓存在BlockCache/RowCache中,缩短这些数据的访问路径。对于那些很少被访问到的数据,可以下沉到LSM-tree的最底层,并压缩存储。
传统LSM-tree的compaction是基于层数阈值或者一层的容量大小阈值触发的,它并不感知数据自身的冷热。一条经常被读取的数据,可能因为时间的推移被推到了LSM-tree的最底层。读取该数据会涉及到对DataBlock的解压,效率低下。因此冷热分离的精准性同时关乎到性能和成本。
为了解决这个问题,我们分析了大量业务的数据访问特征,发现对于绝大部分业务。数据在写入之后,访问频率大致随着时间推移按照指数衰减,但是也会由于某些原因再次变热并被频繁访问。这样一个复杂的特征,传统LRU的模型是难以描述的。
为此我们在X-Engine中除了应用传统的基于统计的模型,还引入了描述能力更强的AI算法。X-Engine中的冷热分离算法主要完成如下几个任务:
- compaciton过程挑选出未来最不可能被访问到的数据页和记录,下推到LSM-tree的更底层。
- 挑选当前热点数据,在compaction或者转储的过程中回填到内存中(BlockCache和RowCache), 避免cache命中率的抖动影响性能。
- 更进一步的,AI算法会识别出未来可能被访问到的数据,提前preload到内存中,减少首次访问的cache miss。
准确识别出数据冷热,可以避免无效压缩或解压带来的算力浪费,提升热点数据在内存中的命中概率,并最终提升系统吞吐。而要做到冷热识别的完全精准非常困难,我们目前做到了基于概率统计模型来挑选compaction目标数据以及挑选回填到内存中的数据页。基于于未来请求特征的预热算法还在研究中(很快会在新的论文中和大家见面),此技术方向我们也在和各大高校如浙大,北大的研究机构进行合作,也欢迎感兴趣的同学加入我们。
我们有一个先进的LSM-tree引擎X-Engine做基础,同时也有阿里巴巴丰富的业务场景数据做支撑。相信我们能在AI For DB上探索出一条切实可行的道路。
4. 写在最后
X-Engine具有LSM-tree天然分层架构带来的优势,可以使用紧凑的数据页存储格式并结合压缩来降低存储空间开销。我们创新设计的事务流水线处理技术,FPGA异构计算加速技术则提升了X-Engine的性能上限。结合智能化的冷热数据分离技术,X-Engine同时兼具了成本和性能的优势。
除了服务于钉钉业务之外,X-Engine 在阿里巴巴内部也被大量业务所采用,并在线上经过了三四年的锤炼。目前X-Engine也在阿里云RDS MySQL作为一个可选存储引擎售卖,点击阅读原文了解等多详情。
在未来X-Engine作为PolarDB分布式版本的一个底层存储引擎,将在分布式数据库领域服务更多的客户。