本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权。
引言
写放大(Write amplification)原本指的是在SSD上的一种介质本身的现象,即实际写入介质的数据量大于请求本身的数据量[1],由英特尔和SiliconSystems第一次提出[7][8],后来这个名词的含义逐渐宽泛了起来,即描述的是这种行为而不是特定的介质上的一种行为。早在大三的时候就写过一篇博客阐述过Dirtect IO可能造成的写放大问题的原因(虽然那篇文章存在一定的问题),后来发现LSM Tree本身也会造成写放大问题,并且这也是一个热门的研究方向[4][2][3],当然其本身对于工业应用也是具有很大意义的,因为多次的写入代表着磁盘带宽的消耗过大,存储空间代表着成本,虽然存储(SSD,HDD)中IOPS和吞吐才是衡量的重点,但是写放大也会对应用造成一定的影响。
这篇文章中简单总结下LSM Tree写放大的几种优化方式,当然这方面的论文实在是太多了,只是满足自身的好奇以及学习下别人的思路,提升广度,希望能在后续工作与学习中产生一些启发,深度方面还是自己探索读论文最为清楚。
性能评估
在[10]中给出了LSM树(leveling merge policy)与B+树的写放大性能对比。
基于层次的意思是每个level被视为一个component,每次level i-1都会和level i合并以后再并入level i,以此类推,当然每个level的大小都有其本身的限制,这会导致level i中的数据被写入多次,当然不同版本的数据也可能存在于多个level中(与前者相关),这两者都是导致写放大的现象。
我们假设level i+1是level i的k倍,所以: l e v e l i + 1 = k ∗ l e v e l i level_{i+1} = k * level_i leveli+1=k∗leveli
假设N是数据库的大小,B是最小的level文件的大小,即层数为: O ( l o g k N / B ) O(log_kN/B) O(logkN/B)
所以总的写开销是: O ( k ∗ l o g k N / B ) O(k*log_kN/B) O(k∗logkN/B)
读的总开销是: O ( l o g 2 N / B l o g k ) O(\frac{log_2N/B}{logk}) O(logklog2N/B)
与B+树的比较如下:
当然这里提到的是base level的,还有一种 base Tiering的策略,其和base level策略的性能对比如下[4],因为和上面那篇文章两者设置的变量不一样,所以式子有一些区别:
优化方案
Wisckey
优化的思路是:
- 数据长度越大,越容易触发Compaction,从而造成写放大,并且每次写都会带上Value,但这一操作是无意义的,只会增大写放大的比例;
- 如果把上层文件看做下层文件的cache,大数据长度会造成这个cache能cache的数据个数变少,从而读请求更大概率的需要访问下层数据,从而造成读放大;
基于此提出了一种基于键值分离的思路去减少写放大,虽然会带来一些问题,比如并发写入(value的随机写),Value的在线轻量垃圾回收,宕机恢复(修改了原来的Log文件),但是都给出了相应的解决方案。这在大Value的情况下可以带来优秀的读写性能并降低读写放大的情况。这在SSD中尤为有效,PingCAP的TiKV在存储引擎中就使用了这种方案,并开发了titan[11]这个rocksdb的插件。BadgerDB, TerarkDB等也用上了这种优化方案,值得一提的是BadgerDB被用于PingCAP Talent Plan的TinyKV项目中。
MatrixKV
由入选华为天才少年的姚婷提出,她也是万继光老师的学生,万老师现在负责星辰团队,和万老师交流后我有幸进入这个团队和其他同学一起学习,万老师yyds。
因为目前实验结果表明:
- 写停顿主要源于 L0-L1 层之间的大量数据的压缩过程
- 写放大会随着 LSM Tree 的深度增加而不断增大
这篇文章主要在写放大和写停顿(Write Stalls)上做出了贡献,主要设计原则就是让 L0-L1 层之间的压缩开销更小从而减少写停顿;减小 LSM-tree 的深度来减小写放大。这篇文章不像上一篇三言两语能说清楚,有兴趣的朋友直接看原文[4]。
Other
在[4]的3.2节中描述了很多优化,有兴趣的朋友可以再仔细学习。
总结
吾生也有涯,而知也无涯。以有涯随无涯,殆已!已而为知者,殆而已矣!
参考:
- 如何理解SSD的写放大?
- WiscKey: Separating Keys from Values in SSD-Conscious Storage
- MatrixKV: Reducing Write Stalls and Write Amplification in LSM-tree Based KV Stores with a Matrix Container in NVM
- LSM-based storage techniques: a survey
- LSM 优化系列(六)-- 【ATC‘20】MatrixKV : NVM 的PMEM 在 LSM-tree的write stall和写放大上的优化
- LSM 优化系列(三)-- 【ATC‘19】9SILK- Preventing Latency Spikes in Log-Structured Merge Key-Value Stores
- Write amplification wiki en
- Write amplification wiki zh
- 对于 Direct IO 写放大现象的探究
- B-Tree vs LSM-Tree
- titan
- MatrixKV: Reducing Write Stalls in LSM-tree