NVM原生数据库技术解读
为让更多数据库从业者了解数据库领域最新研究成果,熟悉行业前沿发展趋势,腾讯云数据库计划举办系列“DB · 洞见”活动,打造数据库技术交流平台,邀请学界及腾讯技术大咖,解读数据库基础技术创新趋势,分享数据库技术创新成果。
今天为大家带来“DB · 洞见”系列活动第一期的部分内容,由中国人民大学信息学院计算机科学与技术系主任柴云鹏教授解读NVM原生数据库技术,以下是分享实录:
NVM原生数据库概述
今天我分享的主题为“NVM原生数据库技术”,内容分三个部分,主要涉及到下面这五篇VLDB 2021的论文。首先我先来介绍下NVM原生数据库整体的情况。
![e4f0c6c118764b8a2774a4b3e4a9eb46.webp](https://filescdn.proginn.com/f4d341dcdc71e604b309fbba467ba949/e4f0c6c118764b8a2774a4b3e4a9eb46.webp)
现有的数据库系统可以分成OLTP数据库、OLAP数据库和HTAP数据库。
OLAP数据库传统上一直是以磁盘数据库为主,即使到现在很多地方都以SSD为主,但还是采用磁盘数据库技术。从早期的单机架构发展到分布式,从主从到现在的存算分离,磁盘数据库发展出了很多优秀数据库产品,是发展的最快的领域。另外一个分支则是比较高端的内存数据库或一体机,比较典型的就是HANA系统。磁盘数据库和内存数据库的产品区分很明确,定位的场景、价格、容量各方面差距都很大。
OLAP数据库方面也是类似的情况,因为大数据分析的量比较大,还是以磁盘数据库为主。少部分的内存或者GPU数据库速度比较快,但数据规模特别小,所以实际上使用范围也不是特别大。HTAP数据库也一样,传统上也是分磁盘和内存两种介质。
![becb8056b756d5df9e5006c2600e537e.webp](https://filescdn.proginn.com/28768e3ecfdf5683ca9de2dc32605bd5/becb8056b756d5df9e5006c2600e537e.webp)
NVM即非易失内存是近年来新出现的介质。严格来说,NVM指的不是一种介质,而是一系列的介质,包括PCM相变存储器、STT-MRAM、ReRAM忆阻器等,这些介质之间也有很大的差别。NVM产品真正推出是在2019年,由英特尔公司研发,目前已经有了第二代产品。
NVM从性质上看介于磁盘和内存两者之间,性能明显优于外存,存储密度高于DRAM,成本也更低。此外,它还类似于DRAM,可以按位访问,最小的粒度一般还是256B。
![c48d5787f1d000b08ae4934f6db6a501.webp](https://filescdn.proginn.com/9e1be9e24a46c7658530b289aa04db5b/c48d5787f1d000b08ae4934f6db6a501.webp)
NVM这种介质如果后续逐渐成熟,对整个数据库产品会有很大的意义。基于现在的内存数据库或者重新定制NVM原生的数据库,它可以达到内存数据库的性能,而且可以扩展内存空间,达到一个数量级左右,同时也可以帮助OLTP、OLAP、或者HTAP数据库降低成本,数据规模也可以上得去,做得更实用。
但它也带来了很多挑战。首先,因为NVM是一个全新的东西,它既像内存又像外存,可以当成内存去用,但现在不能直接的保持持久化,必须要加额外的汇编指令,如果把它当成外存又好像浪费了它的某些属性,这种情况下怎么去用它就是一个问题。其次,数据库传统当中各个核心模块的技术研究了几十年,如果应用到NVM上就有很多模块需要重新设计。最后,这些年新出的存储性硬件的特性都很强,但NVM介质还存在很多问题,要如何去适应硬件的特性也是个问题。
![df4f93efb1daf762111cbfd52ceb4757.webp](https://filescdn.proginn.com/899d08f5aface1b0bb6589e06c74dfe5/df4f93efb1daf762111cbfd52ceb4757.webp)
首先是最流行的NVM索引研究,在NVM设备出来之前就已经有人在研究了。索引里又可分为几种:第一种是比较快速的Hash索引,但是它不支持范围查询,所以数据库里一般还是有序索引比较多;第二种是基于B-Tree的索引;第三种是基于前缀树的索引;第四种是基于LSM Tree即日志结构合并树的索引,很多人认为从原理上讲它不是很适合NVM,但因为LSM Tree确实有自己的优势,比如说写操作比较好、访问连续、利于压缩,同时NVM的特性又没有想象中那么接近于内存,它的连续和随机写之间差别比较大,所以慢慢很多人也开始研究LSM Tree的NVM化,就是把SSD/NVM都加到这里面,做成一个更大容量但性能比SLM Tree引擎好很多的索引;最后一种是混合索引,即用DRAM加上NVM,它们之间的配合可能是多个索引,也可能是拼接索引,虽然这方面的研究不是特别主流,但因为DRAM性能远远好于NVM,因此混合还是有意义的。
其次是空间的分配,因为NVM和DRAM有很大差别,它多了一个空间分配。再者是日志和恢复,因为NVM本身是关于持久化的,所以NVM的按位访问,它的一种介质既可以持久化,又可以非持久化,这就会带来很大差别。最后是缓冲区。
![e472efbb56e249b077f14364c8d7da4e.webp](https://filescdn.proginn.com/58d859cdfcf3b46954d7bf10d28ba81d/e472efbb56e249b077f14364c8d7da4e.webp)
这部分主要是借助VLDB的这篇论文来介绍现在的NVM产品,以及畅想未来的NVM产品的特性。首先我们先来了解下目前NVM的硬件特性,这些都是业界认可的。
![f3468f6ba552c8c87f7b8f0ac2579068.webp](https://filescdn.proginn.com/52fef38c5920578fc8234dcfa365b7b8/f3468f6ba552c8c87f7b8f0ac2579068.webp)
注:下图中的C1指的是比较早的NVM硬件,上面的介质还是DRAM,只是加了电池或电容。C2、C3是假想的,即假设某些产品用了一些cache和预取器,在这种情况下看各个特征是不是对每一类都适用。C4指的是英特尔已经推出的产品。
![232a01b4677d13888e31e2c43348728f.webp](https://filescdn.proginn.com/31bdcada27a622a31be5e88976a24130/232a01b4677d13888e31e2c43348728f.webp)
前两类都是读写不平衡,store指的是持久化的store,它的延迟和带宽都不匹配。首要的原因是介质的影响,我们现在用的3D XPoint或者PCM实际上就是读快写慢。此外,在延迟方面也和CPU的缓存有很大的关系。
在带宽方面,除了介质的原因外,控制器相关的征用对一些资源也有影响。在数据DRAM中,读的带宽能到76G/s,写的带宽能到42G/s,两者有一定差别,但不是很大。但到了NVM,读是30G/s,写大概是8G/s,差别就比较大。在读写差异这一点上,NVM比内存放大很多,是2.5倍和5.2倍的差别。
![0891ff79bc5c0d599ed5713c88de1004.webp](https://filescdn.proginn.com/742fd3f1136ce349546654f18f289b20/0891ff79bc5c0d599ed5713c88de1004.webp)
![e2c2e5d0dcb48bfae952ea340f0bc4f9.webp](https://filescdn.proginn.com/04332c4c9200d2c1e761d4e018480151/e2c2e5d0dcb48bfae952ea340f0bc4f9.webp)
![7285cb8f49de340e4e85124965d93ea2.webp](https://filescdn.proginn.com/5ddfa7b5942f76d96ff95813c3e2b4a0/7285cb8f49de340e4e85124965d93ea2.webp)
![27dbd86cba568c0bd47e4c41954cf085.webp](https://filescdn.proginn.com/d3dfd44d2aa169bacae2bd6d6154d035/27dbd86cba568c0bd47e4c41954cf085.webp)
第六类是连续访问和随机访问比较快。
最后一类是NVM的并发度有较大的限制。内存能够支持的并发数量比较大,它的性能比较好。但是NVM就不同,读和写的并发度并不一致。
![bdec5f048fb006d615f8f0fedf74dccd.webp](https://filescdn.proginn.com/135e0cfe9e27ea71a00786b20e78fafe/bdec5f048fb006d615f8f0fedf74dccd.webp)
![ead346d1b104c7a6d47c88db9e02df8f.webp](https://filescdn.proginn.com/c5192a162a40f7c9edd66f8d9aeea2c6/ead346d1b104c7a6d47c88db9e02df8f.webp)
NVM原生数据库核心技术
2.1 NVM索引技术
索引方面的研究是最多的,最主流的是基于B+树、B树或前缀树这种树型结构的有序索引,这个对数据库来说可能更重要些。
NVM索引技术的研究前几年做得比较多,大体的研究思路是:树形结构里,最下面一层放到NVM里,前面的中间节点放在DRAM,这样可以减少一些NVM的写入,恢复的时候可以通过最下面一层再把上面一层恢复出来,利用这些减少写来提升性能。
这篇论文实际上是对NVM内存上的哈希索引做了一个比较全面的测评,他选了六种比较常见的、比较新的结构,分别是Level Hash、Clevel Hash、CCEH、Dash、PCLHT、SOFT六个索引。接下来我们先介绍下这六种技术。
![c4468259d90535f1f6d7eda1abe8ee62.webp](https://filescdn.proginn.com/2d1fda4d4241aa5a0aa41e6b849a9ce7/c4468259d90535f1f6d7eda1abe8ee62.webp)
首先,Level Hash和Clevel Hash实际上是一个系列工作,最大的特征是减少和解决哈希冲突。最上面这一层是正常的桶,每两个后面可以加一个bottom层的桶,这个的好处在于,一开始下面的桶是空的,一旦冲突了就可以利用下面的桶往里放。因为冲突的情况不是特别频繁,所以它的容量比上面正常TOP层的要少一半,关键是左右两个分支都可以共用这样的结构。这就从空间利用上和减小哈希冲突的开销上起到了trade off的作用。
Clevel Hash也是类似的,可能是更深层次和动态决定的多层结构。上面也用了哈希,有两个哈希尽可能的减少冲突,涉及了log-free这种slot级别的锁来优化它。
![c9ce2e899a954260756ecbb6c0b7f095.webp](https://filescdn.proginn.com/663a4322f66fa7e027e870399a57a343/c9ce2e899a954260756ecbb6c0b7f095.webp)
它解决哈希冲突的最原始版本就是,当冲突时把segment翻倍,再扩大一个segment,这样第二个冲突就可以写到后面新的segment里,这种叫Extendible,它可以很灵活地扩展哈希表的空间。但如果直接用也会产生问题,为了一个bucket冲突去扩展segment,那这个segment上下会有很多空置,平均算下来空间利用率很低。所以这里也做了一些改进,先去做探索,尽可能提高segment里的空间利用率,实在不行再去做扩展,也有一些lazy的策略减少开销。
![b658936e2a8fe9446c22d3ba81607abf.webp](https://filescdn.proginn.com/f856d9881eda1127879fc3dd04731cf4/b658936e2a8fe9446c22d3ba81607abf.webp)
![5272fce1b1b272f122d6486bc4e59e02.webp](https://filescdn.proginn.com/443757cafe4e53033c81da6865e30ed1/5272fce1b1b272f122d6486bc4e59e02.webp)
最后两个都是链式的哈希表。PCLHT是链式的并发哈希,它原来有DRAM的版本,后面做了NVM的改进,包括对cache的友好,原则性的访问等等。SOFT的特点是,有VM的部分,也有NVM的部分,它的数据在这两边都会存。
![8df6f5f61b6f72d83e8a3748320ae882.webp](https://filescdn.proginn.com/6f325a6406fd080f3597e7dfaaa8ceb2/8df6f5f61b6f72d83e8a3748320ae882.webp)
![6e18f6ce76c87a6c283fe4b0aaf9d560.webp](https://filescdn.proginn.com/42d4e855d4e60a642b4b4723e6a1f166/6e18f6ce76c87a6c283fe4b0aaf9d560.webp)
下图中这个值代表内存利用率。Dash也是基于CCEH做了空间的改进,确实是最优。中间这个图是它的PM写放大,最下面这个灰色的是它原始的写入,其他的都是放大出来的,所以可以很清楚地看到谁放大得比较多,像SOFT、CCEH这两个写放大比较少,所以它的性能确实是比较好。
在恢复时间上这几个都差不多,只有SOFT有点差,这方面是它典型的劣势,且SOFT没办法扩展,现在还不是特别实用,但其他几个索引还是不错的。
![2fed302e249035b67df391ff6003856b.webp](https://filescdn.proginn.com/98be9c9c671844848443a3dac1de6092/2fed302e249035b67df391ff6003856b.webp)
![87ee3ba8d0db6574e87645f415317afc.webp](https://filescdn.proginn.com/89ac68a63cadb140c1df2665ac9b2f63/87ee3ba8d0db6574e87645f415317afc.webp)
第二部分介绍日志技术。日志传统上采用的是WAL,它的好处有很多,首要的是可以更好地利用buffer。我们写入设备主要是连续写,性能还是不错的,但缺点是数据和日志要写两遍,这个会有一定的开销。
这方面之前比较经典的研究是VLDB 2016 的WBL,它和WAL是相反的两种很典型的技术。它最大的诉求是只写一遍。为了达到这个目标,它把日志缩得很小,只有一些元信息和时间信息,而数据不用放到日志里。数据再读完后直接写到下面持久化的设备里,上面是volatile,下面是durable,它实际上是写完buffer之后先写数据,但是是以MVCC的方式去写。当一个数要提交的时候,必须保证是写到数据表里,这时数据才能提交。这样的话,写放大明显减少了,带来更大的好处是,因为数据不在日志里,是在表里,不用扫数据,也不用去重构,所以它的回来时间可以忽略不计,速度达到上百倍的提升。
今天介绍的这两篇论文,实际上在事务、日志和恢复这方面都是沿着WBL的思路,但也会有一些新的东西。
![ced1f2529e88477568fa6559daa8507e.webp](https://filescdn.proginn.com/8425178a2a6a7c6d5508888259b11a22/ced1f2529e88477568fa6559daa8507e.webp)
第一个是元数据要进行频繁的修改,尤其是在事务执行过程中为了进行闭环控制,需要有很多元数据的修改。传统上我们会把元数据持久化保存到持久化设备中,比如说NVM里,带来的小粒度随机写是很多的,这个是很大的性能开销。第二个是WAL的数据、日志写两遍的问题。第三个则是WAL的空间分配有其特殊的问题。
DRAM的空间分配之所以简单,是因为当DRAM真正宕机去恢复的时候,实际上系统是从空的开始,只需要从日志里构建内存的东西就行。但是在NVM里,它的数据是非易失的,所以当它重启后,里面的数据是直接去用的,而不是播放一遍日志去重建,所以这时每个分配出来的空间到底用没用,一定要把元数据弄清楚,不然就会出现空间的泄露或者是不一致。
![28f2cd33aa43d685538d54b0e919d63e.webp](https://filescdn.proginn.com/98b93fa68c055d68665c27de707097ab/28f2cd33aa43d685538d54b0e919d63e.webp)
第一种是基于传统的内存数据库扩展,比如用部分NVM空间去扩展这些内存的空间,因为NVM可以当成易失的模式,还有一部分NVM当成非易失的模式,用来存日志,这是一个简单又典型的思路,也能基于现有的内存数据库的代码进行继承和修改。
但是它有两个缺点:第一个缺点是有三份重复写,除了传统WAL和checkpoint这两部分外,volatile的NVM也充当DRAM的角色,但是它的写实际上要比DRAM要慢,所以一个数据可能先要写到这边,然后再写到日志里,它的写放大会更严重。第二个缺点是数据规模在增大的时候,DRAM起的作用会越来越小,主要还是NVM来起作用,所以它的性能会随着使用下降,由NVM来去制约。
![f83178ed6b75f4c75be621a17db7f34a.webp](https://filescdn.proginn.com/fa2f0c5514c820e34a4bce7cdf0c0152/f83178ed6b75f4c75be621a17db7f34a.webp)
第三种是WAL,每一个数据有两个指针,一个指向内存里的page cache,一个指向NVM当中的快照,cache有的就从这读,没有的从快照里读,从日志的角度看还是WAL,但它的性能相对是比较差的。
![fec8d020f241230eab1c92127b760f52.webp](https://filescdn.proginn.com/3ce83826a7a9474b9acc50fcef4ff822/fec8d020f241230eab1c92127b760f52.webp)
第一个重要的技术是matcache in DRAM,就是要尽可能的把DRAM的性能用好。它存储的形式是:DRAM的索引不持久化,全在DRAM里,很多元数据也都在这里面,包括分配器的元数据,尽量把内存的空间用完,全都用做缓存,NVM里只存少量的元数据还有正常的表。前面说的tuple的元数据在控制过程中用到的元数据的修改,实际上都可以在内存里进行,这样性能就会好很多,可以减少很多NVM的写入。
![f084620cdffe07a6be9c67a04838fc0a.webp](https://filescdn.proginn.com/3b1964ad26b361a94b75fbe9eb055c8b/f084620cdffe07a6be9c67a04838fc0a.webp)
![5d4d3a9984fdffccc56c45f5531db616.webp](https://filescdn.proginn.com/067337901ce70421cea8773f3a89d2a2/5d4d3a9984fdffccc56c45f5531db616.webp)
![b02cb8c54d305920433332d920adafd9.webp](https://filescdn.proginn.com/e8dbecc5f33270a2a8172452d86046f6/b02cb8c54d305920433332d920adafd9.webp)
![75b3218cf0733604844094b057e3bc23.webp](https://filescdn.proginn.com/fda5a75efb5134f39dd328aef3559fb0/75b3218cf0733604844094b057e3bc23.webp)
下图是恢复性能的比较。可以看到第一个方案确实恢复比较差,因为它要去做日志读取,再去做redo,整个过程要80多秒,而后两个方案都是个位数级别。WBL按照它的原则是不需要扫描的,基本上是零点几秒,非常快就能恢复,但因为索引也是要恢复的,也要扫一遍数据,所以也需要几秒的时间。Zen因为它的恢复更复杂些,除了扫一遍数据确定哪些数据提交之后,有一些还要再扫一部分数据,所以它的性能稍慢一点。但这里有个小疑问,论文中的数据规模比较小,如果数据规模更大,把所有的开销都推到恢复,那恢复是否还能做到这样快,这个值得后续探讨。
![cdd9c1f372755caa62c67fad551e012b.webp](https://filescdn.proginn.com/fb894cfac606a1592723b8b8c9dff283/cdd9c1f372755caa62c67fad551e012b.webp)
![24aec7c11bbe89adbd650bffa4679633.webp](https://filescdn.proginn.com/682132e9805ff54a91b08dc9f736a2fa/24aec7c11bbe89adbd650bffa4679633.webp)
![cbf671fc79834db60e8f8fb4d11c626b.webp](https://filescdn.proginn.com/1092221b7fb6d2ce2dba2ffde7a4d1b9/cbf671fc79834db60e8f8fb4d11c626b.webp)
这里和日志最相关的是下面的技术。LSM-tree上可能有很多transaction并行在提交,它关心的是提交的时候怎么持久化。以下图为例,这里有并行大量的持久化,为了让力度更大就会把它变成批次来写,但每一批怎么能做到lock-free呢?它计两个值,两个gidx,1就是1号版本,2是2号版本,3是3号版本。前面的值指的是之前已经提交的正确版本,后面就表示当前正在提交的版本。
在这个例子中,当前是1、2的状态,前两个批次已经都提交了,现在正在提交第3个批次,第3个批次第一个已经提交完了,第二、第三个还没提交完,但是后面这个节点就挂掉了,挂掉之后在恢复的时候,因为这个地方是持久化的,它知道正在做2的过程中出问题了,我们只要回到上一个2就行了,如果前面这失败了,再回滚到前面这个2就可以了,前面这个就不用管了,有一部分更新到3,最后也可以回滚到2,所以不会出问题,而且整个过程是必须要写日志的。
![ccb8ec5d6a1eb257ad4a1b65a8163e01.webp](https://filescdn.proginn.com/bac6acb2eb3871281211b68049779c6f/ccb8ec5d6a1eb257ad4a1b65a8163e01.webp)
![4a35211a32379c0e5905102e2cd24272.webp](https://filescdn.proginn.com/abbfb1e4a3255d13bb16c18353a004a4/4a35211a32379c0e5905102e2cd24272.webp)
最后要分享的这篇论文,将介绍NVM的混合内存技术。
此前很多研究都假设NVM与内存比较接近,因此尽量要用NVM直接去写,不做写放大,避免重复的写,但实际上两者性能差别很大,因此还是要用好NVM。如何让DRAM和cache进行分工协作,就成为了一个很重要的问题,这篇论文就是按照这样的思路来开展研究的。
![e8d64c376d421c4958f83142b3a845c7.webp](https://filescdn.proginn.com/49c5d20fc9e687f8486bee0577e6514d/e8d64c376d421c4958f83142b3a845c7.webp)
![57f3ce9e68a13a072fbb7ea4305d3863.webp](https://filescdn.proginn.com/42d467d5221d192af34c0b0aca2faf1c/57f3ce9e68a13a072fbb7ea4305d3863.webp)
这里有一个值得学习的比较通用的小技巧,即如何让NVM的元数据持久化的开销尽可能小。要先写数据,再写元数据,且要保证元数据是8字节内的原子写,这样就不需要WAL。在下面这个例子中,先把数据写进去,写完之后,把beat从0改成1,这个小beat肯定是原子写的。如果前面这个过程挂掉了,这个数据因为beat没有set,我们就知道这个数据没写成功,甚至空间都没有分配出去,那就可以直接下次再用。如果已经写完了1,说明上面肯定是完成的。通过这个技巧可以减少很多开销。
![e8e0350fa02b54d08786ad27a73c256c.webp](https://filescdn.proginn.com/87e57c349f4fd24d18feaf1171677893/e8e0350fa02b54d08786ad27a73c256c.webp)
总结与思考
在很长时间内,NVM介质还是明显弱于DRAM。目前只有英特尔公司在做NVM产品,其发展不会很快,迭代的周期也会很长,所以前面介绍的硬件特性可能会长期存在,这也给未来数据库的发展带来了更多的机会。
如果要和内存数据库、磁盘数据库做对比,实际上NVM数据库应该更接近于内存数据库。因此基于内存数据库去改造NVM数据库要更方便,当然也可以是原生的重新设计,这样效果可能会更好。
但NVM数据库和内存数据库虽然接近,实际上两者还是有较大的差别。
一方面,内存数据库的空间是受限的,场景和成本都是它的问题,而NVM数据库在存储力度、成本上有较大的优势,将来可能会应用在很多场景里。另一方面,内存数据库的日志持久化部分也带来较大的性能开销,而NVM数据库在这方面还会有较多的提升空间,即使是从内存数据库优化的角度,也能让内存数据库的性能更好。
![9b44bdc11624ee146afbc583f262077f.webp](https://filescdn.proginn.com/7971e5e6364aa36d8d84acdc279e84e7/9b44bdc11624ee146afbc583f262077f.webp)
![1de6d90b3f3f502eed8dfd4919361ec8.webp](https://filescdn.proginn.com/3903f0c680850330312d001fe89fff7a/1de6d90b3f3f502eed8dfd4919361ec8.webp)
﹀
﹀
﹀
![009358838e85b3db6d07d16dc66bdc6f.webp](https://filescdn.proginn.com/99a4a20512a949eea9f6eccb6c3aed30/009358838e85b3db6d07d16dc66bdc6f.webp)
解锁数据库前沿技术要点 | 腾讯云数据库DTCC 2021亮点回顾
![ad0c271374b52a28eb225ca490f16c4a.webp](https://filescdn.proginn.com/5eaf07087b1a19c30ae2d570c75bbef6/ad0c271374b52a28eb225ca490f16c4a.webp)
首例“微服务+国产分布式数据库”架构,TDSQL助力昆山农商行换“心”
![95aebdc061caf8df8b8e72c224fcc0c2.webp](https://filescdn.proginn.com/754b044557b1e519207361f24051742e/95aebdc061caf8df8b8e72c224fcc0c2.webp)
数实融合·绽放新机,Techo Day技术回响日邀您“云相聚”
点击阅读原文,了解更多优惠福利!