MyRocks是完全兼容MySQL的一个关系型数据库系统,由Facebook于2016年下半年开源,网易杭研数据库内核团队在2018年初引入,在网易云音乐个别业务场景落地使用,取得了较好的疗效,在这以后落地了更多地业务场景。
自己整理的Java构架学习视频和大厂项目底层知识点,需要的同事欢迎私信我【资料】发给你~一起学习进步!
简述
MyRocks是Facebook数据库工程团队将MySQL的默认储存引擎InnoDB(基于B+树)替换为自家的RocksDB(基于LSM树)后发展而至的MySQL分支版本,其承继了MySQL的SQL句型,数据高可用框架和配套工具。
MyRocks具有较高的普适性,对于MySQL用户来说,将MySQL替换为MyRocks是透明的,在使用方面并没有差距。最大的不同是DML操作(数据操作词句,如增、删、改)性能相比MySQL有显著优势;同样的数据量,所需的储存空间显著变少。
目前MyRocks在云音乐内使用,业务场景包括云音乐实时推荐、离线推荐、历史听歌记录、P0核心库延后从库和云估算NOS系统内部数据管理等等,累计节约了百万级的成本开支。
项目介绍
MyRocks是MySQL和RocksDB的结合,MySQL是目前最流行的开源关系型数据库系统,RocksDB是Facebook在Google的LevelDB基础上改进的KV储存引擎。
RocksDB简介
RocksDB基于Log Structured Merge Tree(LSM树)存储数据,下面简单介绍下RocksDB。
如上图所示。在RocksDB中,LSM可有多层,图中为4层(L0~L3),每一层就会独立进行Compaction操作;可以为每位用户数据表/索引创建一个列族(CF),每个CF都是一颗LSM树;每颗LSM树就会有数个Write Buffer(MemTable),用于缓存早已递交的事务数据;事务递交时会将WAL(Write Ahead Log)持久化到全局的日志文件中。
每个事务都有一个writebatch对象,用于缓存该事务在递交前更改的所有数据。在事务递交时,其更改的数据先写入WAL日志buffer,根据配置参数选择是否持久化。然后将更改的数据有序写入到Active MemTable中。当Active MemTable达到阀值后会变为Immutable,再新形成一个Active MemTable。
数据写入MemTable后就意味着事务早已递交。数据的持久化和Compaction都是异步进行的。当Immutable MemTable个数达到所设置的参数阀值后,会被回刷成L0 SST文件。在L0文件个数达到阀值后,合并到L1上并依次往下刷。RocksDB中可以配置多个线程用于对每层数据文件进行Compaction。
由于其优秀的特征,目前早已被集成到MySQL(即MyRocks)、MongoDB(即MongoRocks)、TiDB/TiKV和Nebula等关系型数据库、文档数据库、分布式KV、NewSQL和图数据库中,成为实际上的KV存储引擎标准。
【MyRocks优缺点】
MyRocks承继了MySQL优秀的基因,包括完全兼容的MySQL SQL句型、行级锁细度、读已递交(RC)和可重复读(RR)两种事务隔离级别、多版本并发控制(MVCC,Multi-Version ConCurrent Control)、成熟的主从复制框架和建立的配套工具等功能和特点。
核心竞争力
由于引入RocksDB,MyRocks具备比MySQL(相比基于B+树的InnoDB)更多优点,如更快的写入速率,更小的储存空间,更高的压缩效率等;这是MyRocks的核心竞争力,下面简单对比说明。
InnoDB是典型的B/B+树存取方法,即使是次序插入场景,也会在一个page还未完全塞满时触发分裂,变为2个半空的page,也就是说InnoDB的page一定存在页内碎片。
而RocksDB因为是追加(Append)方式,所以都是文件次序写行为;MemTable从显存 Flush到c盘后成为独立的sst文件,不同的sst文件间的Merge操作也是次序读写,整个过程均不会形成内部碎片。
即使在非压缩模式下,RocksDB记录也进行了前缀压缩/编码,默认每16条记录才有一条是完整的,节省了后续15条记录的共同前缀所需的储存空间。
此外,RocksDB每位索引占用7+1 bytes(seq id + flag)的元数据开支,而InnoDB每记录6+7 bytes (trx_id + undo ptr)空间开支,似乎在多个索引的场景下RocksDB愈发费空间,但Ln SST文件seq id可置0,经过压缩等操作后绝大部分元数据开支是可节省的,只需占用1byte,因此RocksDB的元数据开支也比InnoDB更省。
在压缩效率方面,也是RocksDB更抢占优势。InnoDB压缩以page/block为单位来独立保持压缩后的数据,而文件系统是须要块对齐的,一般都是4KB,这就意味着一个16KB的页,即使压缩为5KB,也须要使用2个文件block,即8K保存。其中的3KB空间填空。
RocksDB挺好得解决了这个问题。每个block压缩后,先组合成一个SST文件,保存时只须要SST文件对齐到4KB即可。
不足
在性能上,MyRocks相比InnoDB不足之处在于查询性能(主要是范围查询),在这方面,MyRocks通过使用布隆过滤器(Bloom Filter)进行了查询优化。
相对来说,MyRocks作为一个年青的开源项目,相比MySQL/InnoDB在成熟度上和功能完整度上有所缺乏,包括XA事务支持度不够、在线DDL性能不足且显存消耗过大、支持的索引类型偏少(无地理位置索引、全文索引等)等。此外,Bug数也更多。
【使用场景和实际疗效】
由于MyRocks完全兼容MySQL,因此,对于通常的,比如读写压力都不大、只需关系型数据库基本功能的业务场景下,MyRocks是完全可以取代MySQL的,但这不是MyRocks项目的存在意义,因为带来不了多少价值。
MyRocks应当用在相比现有方案才能显著形成更多价值的场景,下面列出MyRocks典型的应用场景,并介绍在部份场景上的使用疗效。
大数据量场景
这类场景典型的特征是数据量大,此外可能数据下降也很快,也可能有过期删掉的需求等,这类场景包括用户行为,动态等。我们曾与DBA对云音乐和考拉等业务的MySQL实例进行应用场景剖析,发现这类场景的MySQL实例占有不小的百分比。
MyRocks因为具备更高地压缩比,可以极大缩小数据的储存空间。降低这部份业务的储存开支。而且MyRocks支持数据TTL(Time To Live)特性,可以设定数据过期时间,更加便捷进行数据生命周期管理。
目前云音乐有多个这类业务场景使用了MyRocks,这里拿云音乐的用户历史听歌记录为例。
在没替换为MyRocks前,历史听歌记录为一个下挂有16个MySQL高可用实例的DDB集群。数据采用InnoDB压缩表方式储存,每个节点数据约1TB,整个集群共32TB,如上图所示。下图为替换为MyRocks后的情况,设置RocksDB的压缩算法为Snappy,单个节点的数据量降为322GB,节省了700GB。整个集群可省下20TB SSD盘,节省了超过2/3的存储成本;由于估算资源利用率低,存储缩小后,可提升数学服务器的MyRocks实例布署密度,进一步节约估算资源;同时数据增长速度也得到控制,集群扩容周期变长。
写密集型场景
这类场景的特征是数据量不小,对写性能要求超过了MySQL/InnoDB的能力,且对读的延后和平稳性有较高要求。如果仅需高写入能力,那么可选择分布式KV系统,比如HBase,其提供了不弱于MyRocks的写入能力,且扩展性更好。但若对读性能有较高要求,那么选择MyRocks会更好,因为基于C++实现的MyRocks没有Java的GC等问题,性能愈发平稳。
如果是数据量较小,且对读写均有较高要求的场景,可采用Redis等缓存方案。但若业务场景的数据量较大,使用缓存的方案成本都会偏低。
这类场景有推荐类、业务流水和日志类等等。在网易公司内部各部门均广泛存在类似的场景,目前云音乐的实时推荐、离线推荐等,NOS内部数据反查服务等均已使用MyRocks,这里举云音乐实时推荐为例。
在本案例中主要还是关心成本。因为数据量比较大,需要大量的显存,而且随着推荐的实时化改进和推荐场景的增多,内存使用成本大幅降低,甚至可能出现显存采购来不及的情况。
显然,单个MyRocks肯定扛不住全部的压力,于是仍采用DDB+MyRocks的形式将压力分拆到多个实例上。但落到MyRocks的写入压力仍较大,虽MyRocks主库才能扛住,但因为MySQL主从复制跟不上,所以MyRocks从库延后不断降低。由于推荐类业务对数据一致性有一定的容忍度,所以,最终落地的方案是业务层词尾2个MyRocks而不是MyRocks层做主从复制。下图为当前的布署构架。
图短发左右两部份,左边为8个MyRocks节点组成的DDB1集群,右边也是8个MyRocks组成的DDB2集群,推荐算法逻辑相关的单元用Flink来表示。算法单元从DDB1读取上一周期的推荐数据,跟当前实时变化的新数据相结合估算出本周期的推荐数据,然后将其分别写入DDB1和DDB2。推荐业务使用方从DDB2上读取所需的推荐数据。
上图为经过参数调优后的MyRocks节点性能表现,DDB1上的节点读写QPS/TPS达到1.5w/s,DDB2上的业务读QPS达到0.5w/s,读延后大部分时间均在2ms以下,平稳度高,波动小。
总的来说,实时推荐通过将Redis替换为MyRocks集群,在性能上扛住了业务负载的情况下有效减少了所需投入的硬件成本。
其他适用场景
依托高写入性能和低储存开支的特性,MyRocks还可作为MySQL高可用实例的低成本从库,比如避免数据删掉的延后从库(比线上数据延后n个小时),用于数据导出的专用从库等。目前云音乐的歌单、用户和曲库等所有P0级的MySQL核心库,均构建了延后从库,这些节点都部署在同一个物理机服务器上,每个节点仅需5G显存,原数据量1/3以下的储存空间,如下图所示。基于MyRocks的延后从库以特别低的成本换来了核心业务数据更高的安全保障。
除了前面所述的场景外,还有更多其他场景可以使用MyRocks,在此不一一展开说明。
【使用心得】
当然,MyRocks在落地使用过程并不是一帆风顺的。在新的场景类型落地时遇见了不少问题,杭研的数据库内核团队和杭研DBA、业务开发一道为最终的推广使用做了至关重要的贡献,包括对MyRocks进行功能提高、BugFix、参数调优和使用经验输出等。下面举例介绍。
1.问题与优化
在使用过程中,我们发觉、定位和解决了数十个大大小小的问题,对MyRocks进行优化提高来满足业务需求。先后发布了3个MyRocks内核版本,其中第一个版本将开源的MyRocks代码合入杭研MySQL分支InnoSQL中,后两个版本(v4a和v4b)均是对MyRocks的优化提高和BugFix。
InnoSQL 5.7.20-v4a:
InnoSQL 5.7.20-v4b:
2.MyRocks XA事务提高
这里要展开说的是我们为MyRocks降低了完整的XA事务处理能力,这是MyRocks想要在网易内部大规模使用所必备的能力。因为网易诸多业务均使用DDB作为MySQL分库分表的解决方案,而DDB可能会大量形成XA事务。
开源版MyRocks仅支持执行XA事务,但不支持回放XA事务,因为XA事务PREPARE后对应Session不能执行除XA COMMIT或XA ROLLBACK外其他操作,这在主库是没有问题的,可以通过创建新的Session执行其他事务操作,但在Slave端,用于回放事务的worker线程(等同于主库的Session)是有限的。这种情况下,也就是说假如存在XA事务,那么就没法使用MyRocks高可用实例,其原因是MySQL的XA事务复制框架与储存引擎强相关。
MyRocks并没有适配这套框架,如在XA START和PREPARE时必须的detach/reattach操作等,杭研数据库内核团队参考InnoDB实现了MyRocks的XA事务相关API插口。
除了实现API接口外,由于目前MySQL官方仅有InnoDB一个支持事务的储存引擎,所以MySQL对多储存引擎混和的XA事务支持上有较大问题,最典型的问题是多种不同缘由造成的内存泄露;此外,我们发觉MyRocks的XA PREPARE并未进行WAL持久化,会导致mysqld crash后数据遗失。这些问题均通过源码级剖析完成问题定位并得到了有效解决。
3.参数调优
RocksDB有数百个配置参数,其中曝露到MySQL上的有100+个。这些参数影响了MyRocks显存使用、MyRocks性能和数据持久性等方方面面,需要按照不同的业务场景进行最优化配置。
合理配置显存相关参数
MyRocks与显存相关的参数较多,如block cache、MemTable和CF相关配置等。设置过小可能影响写性能,设置过大可能造成OOM。
在云音乐历史听歌记录场景下,我们原本采用每位用户数据表一个CF的配置方案。由于每位CF均有独立的MemTable,会抢占几百MB甚至数GB的显存空间,而该场景下每位MyRocks实例有较多数据表,出现由于MemTable抢占显存过多而OOM的情况。所以须要合理规划CF个数,每个CF的MemTable总大小因为max_write_buffer_size,max_write_buffer_number*等4个参数共同决定,其大小会影响该CF的写性能,应按照业务场景进行合理配置。
除了参数调优,在显存使用方面,我们还进行了源码级优化,包括曝露更具体的MemTable显存使用现况,替换更高效的系统内存分配器等。
合理配置Compaction相关参数
Compaction相关参数较多,对于写密集型业务,若配置不当会导致业务停写问题(write stall)。在云音乐实时推荐场景,我们通过合理调优Compaction参数来实现MyRocks读写性能平稳输出。
上图右上侧为未调优时的性能曲线,波动十分剧烈,最高1w+,最低仅2k+。这是因为写入压力过大频繁触发停写问题。
显然,进行参数调优时,如果参数就能在线调整,可以避免数据库服务重启造成业务受影响,所以我们通过代码优化尽可能降低了在线可调的参数个数。
【推荐理由】
一、 MyRocks拓展了MySQL应用领域,使其可以在要求更高性能的业务场景上使用;
二、 MyRocks降低了MySQL所需的储存空间,节省了业务的硬件投入成本;
三、 有大量MyRocks才能发挥优势的使用场景。