小镇的夕阳|深度 | X-Engine的In-Memory读性能优化
作者:顾绅/北楼
背景虽然同为LSM-tree架构 , X-Engine的设计哲学与传统基于LSM-tree架构的Rocksdb等引擎并不完全一致 , 如下图所示:
设计关键点1:X-Engine磁盘上的数据 , 在常态下只有两层(L1/L2) , L0层是MemTable在compaction来不及的情况下暂存到磁盘上缓解内存压力时才启用的 , 正常情况下被冻结的MemTable可以直接和磁盘上的L1合并 。
设计关键点2:在L1/L2之间的compaction合并过程中 , X-Engine的冷热合并算法倾向于将热点数据保留在L1层(基于访问频度) , 将访问较少的数据下刷到L2层并进行压缩存储 。 这是一个对数据在物理上进行冷热分离的过程 ,其结果是L1存储的都是热点数据 , L2存储的都是冷数据 。 对L1进行缓存时会有更高的内存利用率 。
按照设计初衷 , X-Engine正常运行时 , Memtable中缓存了最近写入还未刷盘的数据 , L1中保存了磁盘访问频度最高的数据 , 也大部分被内存缓存 , 分层之后X-Engine的读性能优化被分解为两个独立子问题:
- 内存MemTable部分和L1层数据读操作是CPU bound的 , 手段主要是优化CPU指令的执行效率和访问主存的速度 。
- L2层的读性能依赖于磁盘的随机读能力 , 对此部分的优化手段是更精准的冷热识别 , 其目标是最大化IOPS利用率 。
读取路径存在的问题在数据集小于可用内存时 , X-Engine的读性能受限于CPU资源 。 分析一个CPU bound程序的性能问题时 , 我们需要看CPU在哪些地方繁忙 。 按照CPU使用率的定义 , CPU在执行指令时或者在等待数据时(stall) 都会处于busy状态 , 存储引擎的读性能优化最后都会落到两个点上:
- 提升CPU Cache命中率 , 主要靠执行线程在时间上和空间上访存的局部性 。
- 提升CPU指令的执行效率 , 这一方面需要精简实现代码 , 减少不必要的执行路径 , 另一方面需要减少不同线程之间的状态同步 , 保证指令流水线顺畅执行 。
- ExtentMeta数组是这棵B+树的根节点 , 在其中二分查找定位出X所属的Extent.
- Extent可以理解为一棵子树 , 首先需要通过一次Hash查找(查询缓存)获取到该Extent的IndexBlock 。
- 从IndexBlock中定位出X所属的DataBlock的Key ,并通过一次Hash查找定位到X所属的DataBlock 。
- 在内存中的DataBlock中查找到该记录的实际内容 , 并返回对应的Value.
接下来我们将详述这三个问题的根源以及我们的优化方法 , 最后通过实验对每一步优化手段的收益进行了评估 。 考虑到这三个问题在数据库存储引擎中的普遍性 , 这些优化方法对于InnoDB, Rocksdb等引擎也是适用的 。
推荐阅读
- 【】新闻调查:决战深度贫困
- 深度解娱SJ|陈小纭怎么不会知道绿色含义,先暗示自己被绿又出面解释,看不懂
- 央视网|新闻调查:决战深度贫困
- 新闻调查:决战深度贫困
- :iPhone 12不再附送充电器,深度分析苹果为哪般
- 央视网|修村路、建水厂、搬新居……决战“三区三州”深度贫困
- 央视新闻客户端|修村路、建水厂、搬新居……决战“三区三州”深度贫困
- 一个|修村路、建水厂、搬新居……决战“三区三州”深度贫困
- 趣事奇文007|外地人去了担惊受怕,本地人却乐在其中,被巨石“压着”的小镇
- 篮球国度|为什么哈登喜欢威少却讨厌保罗?,深度分析:都是NBA顶级控卫