跃居AppStore第一!X-Engine如何支撑钉钉数据量激增
钉钉作为国内领先的企业IM工具,在中国有超过亿级别的用户。随着新型冠状病毒肺炎疫情的爆发,大量的企业员工选择了soho模式,企业办公协同工具的需求瞬间爆发。
钉钉作为中国企业办公IM的首选应用,不仅具有项目群、视频通话、视频会议、日报、打卡、远程投屏等基础能力,还具备深度、灵活订制各种 OA (Office Automation,办公室自动化) 应用的能力,极大方便了人与人之间的链接,可以帮助企业员工快速、高效地沟通和协作。

也因此,钉钉迅速冲上了AppStore下载免费榜单的第一位。瞬间爆发的在线办公需求,导致钉钉的访问流量激增。每天早晨的打卡风暴,迅速增长的聊天信息,一次次的流量洪峰冲击着钉钉的业务后台。但是借助于阿里云提供的弹性基础设施,钉钉平稳的渡过了每一次的流量洪峰。
在亿级别的用户体量下,钉钉的消息系统,除了要保证消息及时正确地传递,还要保证已读/未读等特有功能。而且不同于市场上常见的用户级IM工具,企业IM需要实现聊天记录的永久保存,并且提供多端漫游功能。
在用户量持续爆炸性增长的前提下,聊天记录永久保存给钉钉业务带来极大的成本压力。同时在数据爆炸的前提下保证聊天记录的读写性能不降低也是一个极大的挑战。
面对这些挑战,钉钉业务选用了X-Engine作为全量钉钉消息的最终存储引擎,实现了性能和成本的平衡。而且在此次企业协同办公需求爆发期间,钉钉业务的数据库系统顶住了所有的流量洪峰。
为什么是 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倍的优势。

X-Engine架构
在阐述为什么X-Engine可以节约这么多存储成本之前,我们先看看它的整体架构。
X-Engine采用了LSM-tree典型架构。在LSM-tree的数据组织下,写入的数据首先进入一个内存表中,对该部分数据的读写都是在内存中进行,因此访问最新的数据有着最高的效率。
在内存表的大小达到一定阈值之后,将会冻结进行转储,并持久化到磁盘上。X-Engine在磁盘上的数据也是分层的,随着时间的推移,compaction过程会根据数据的访问频度,将最冷的数据转移到LSM-tree的最底层并进行压缩。因此访问最少最冷的数据有着最长的访问路径,而温度稍高的数据访问路径更短。

数据分层的架构,让我们可以对不同的数据集采用不同的处理模型。例如对于新写入的数据,使用高度并发的事务流水线技术,这项技术可以提高极高的写入吞吐。而对于占整体数据量95%以上的底层数据,使用紧凑编码并进行压缩,以降低空间。而对于底层数据中散布的部分热点数据,则充分使用BlockCache和RowCache来加速读操作。
X-Engine如何有效降低成本
目前广泛使用的InnoDB引擎也是可以通过开启压缩来降低存储空间的,那为什么在钉钉IM的消息存储中,X-Engine有着更好的表现呢?因为X-Engine有以下几个独门秘籍:
紧凑的数据页格式
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型存储引擎中,在提升存储效率的前提下保证读取性能是一个值得进一步探讨的话题。
数据压缩及无效记录清理
由于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异构计算加速技术能够提供更优异的成本效益比。更详细的数据可以查看论文匠心之作

压缩及compaction可以减少磁盘空间占用。而FPGA等异构计算设备算力的加持让我们可以不用付出性能的代价。即使在没有FPGA加速卡的机器上,借助合理的调度算法,X-Engine也能以较小的性能代价获得存储空间的节省。
智能冷热分离算法
虽然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上探索出一条切实可行的道路。
写在最后
X-Engine具有LSM-tree天然分层架构带来的优势,可以使用紧凑的数据页存储格式并结合压缩来降低存储空间开销。我们创新设计的事务流水线处理技术,FPGA异构计算加速技术则提升了X-Engine的性能上限。结合智能化的冷热数据分离技术,X-Engine同时兼具了成本和性能的优势。
除了服务于钉钉业务之外,X-Engine 在阿里巴巴内部也被大量业务所采用,并在线上经过了三四年的锤炼。目前X-Engine也在阿里云RDS MySQL作为一个可选存储引擎售卖,点击阅读原文了解等多详情。
在未来X-Engine作为PolarDB分布式版本的一个底层存储引擎,将在分布式数据库领域服务更多的客户。
查看更多:https://yqh.aliyun.com/detail/6214?utm_content=g_1000104982
上云就看云栖号:更多云资讯,上云案例,最佳实践,产品入门,访问:https://yqh.aliyun.com/
跃居AppStore第一!X-Engine如何支撑钉钉数据量激增的更多相关文章
- 机器学习工作流程第一步:如何用Python做数据准备?
这篇的内容是一系列针对在Python中从零开始运用机器学习能力工作流的辅导第一部分,覆盖了从小组开始的算法编程和其他相关工具.最终会成为一套手工制成的机器语言工作包.这次的内容会首先从数据准备开始. ...
- 2.HBase In Action 第一章-HBase简介(1.1数据管理系统:快速学习)
Relational database systems have been around for a few decades and have been hugely successful in so ...
- python第一个爬虫的例子抓取数据到mysql,实测有数据
python3.5 先安装库或者扩展 1 requests第三方扩展库 pip3 install requests 2 pymysql pip3 install pymysql 3 lxml pip3 ...
- angularJS 第一天 使用模型与控制器绑定数据
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script sr ...
- Spark Mllib里如何将trainDara训练数据文件里第一行是字段名不是数据给删除掉(图文详解)
不多说,直接上干货! 具体,见 Hadoop+Spark大数据巨量分析与机器学习整合开发实战的第13章 使用决策树二元分类算法来预测分类StumbleUpon数据集
- ASP.Net 第一天笔记 MVC 控制器与视图数据传递注意事项
1.如果方法的参数的名称与表单元素Name属性的值一致的话,会自动填充 2.如果表单元素的Name属性与实体类型中属性一致,那么表单中的数据会自动赋值给实体中的属性 3.控制器中重载的方法 方法前上边 ...
- 我们知道CDN护航了双11十年,却不知道背后有那么多故事……
情不知如何而起,竟一往情深.恰如我们.十年前,因为相信,所以看见.十年后,就在眼前,看见一切. 当2018天猫双11成交额2135亿元的大屏上,打出这么一段字的时候,参与双11护航的阿里云CDN技术掌 ...
- 【MySQL】MySQL备份和恢复
一.为什么要备份数据 在生产环境中我们数据库可能会遭遇各种各样的不测从而导致数据丢失, 大概分为以下几种. 硬件故障 软件故障 自然灾害 黑客攻击 误操作 (占比最大) 所以, 为了在数据丢失之后能够 ...
- MySQL复合索引探究
复合索引(又称为联合索引),是在多个列上创建的索引.创建复合索引最重要的是列顺序的选择,这关系到索引能否使用上,或者影响多少个谓词条件能使用上索引.复合索引的使用遵循最左匹配原则,只有索引左边的列匹配 ...
- AngularJs 动态加载模块和依赖
最近项目比较忙额,白天要上班,晚上回来还需要做Angular知识点的ppt给同事,毕竟年底要辞职了,项目的后续开发还是需要有人接手的,所以就占用了晚上学习的时间.本来一直不打算写这些第三方插件的学习笔 ...
随机推荐
- stm32 串口DMA调试总结和反思
一 引言 最近在调试stm32的多串口.没想到居然遇到那么多的问题.这里做一个总结,还是非常有必要的. 二 问题 这里先弄清楚几个问题. 1 串口有必要使用DMA吗? DMA可以在串口高速的时候不占用 ...
- 关于使用Kotlin开发SpringBoot项目使用@Transactional和@Autowired的报错问题
原文地址: 关于使用Kotlin开发SpringBoot项目使用@Transactional和@Autowired的报错问题 - Stars-One的杂货小窝 问题描述 最近在开发一个订单模块,需要出 ...
- Ubuntu下安装Android Studio
一.系统环境 二.安装源文件 Android Studio 4.2.2:android-studio-ide-202.7486908-linux.tar.gz Java SE Development ...
- 结构体、共用体与C++基础
结构体.共用体与C++基础 1.结构体 结构体是C编程中一种用户自定义的数据类型,类似于Java的JavaBean //Student 相当于类名 //student和a 可以不定义,表示结构变量,也 ...
- 04_QT_Windows开发环境搭建
FFmpeg 为什么选择FFmpeg? 每个主流平台基本都有自己的音视频开发库(API),用以处理音视频数据,比如: iOS:AVFoundation.AudioUnit等 Android:Media ...
- .Net依赖注入神器Scrutor(上)
前言 从.Net Core 开始,.Net 平台内置了一个轻量,易用的 IOC 的框架,供我们在应用程序中使用,社区内还有很多强大的第三方的依赖注入框架如: Autofac DryIOC Grace ...
- 三维模型3DTile格式轻量化云端处理技术方法分析
三维模型3DTile格式轻量化云端处理技术方法分析 在现代的地理信息系统 (GIS) 中,3D Tiles 是一种很重要的数据格式,用于存储和传输大规模地理空间数据.然而,由于其数据密度高,传输和加载 ...
- 文件与Base64的互转
/** * 本地文件转换成Base64字符串 */ public String convertFileToBase64(String Path) { byte[] data = null; // 读取 ...
- Circle Loss:从统一的相似性对的优化角度进行深度特征学习 | CVPR 2020 Oral
论文提出了Circle loss,不仅能够对类内优化和类间优化进行单独地处理,还能根据不同的相似度值调整对应的梯度.总体而言,Circle loss更灵活,而且优化目标更明确,在多个实验上都有较好的表 ...
- 循环队列(LoopQueue)
循环队列相比普通的队列,元素出队时无需移动大量元素. 代码 ArrayQueue.h 点它 代码清单 #ifndef C___LOOPQUEUE_H #define C___LOOPQUEUE_H # ...