论文导读|基于机器学习的高速缓存预取

 

作者:北京大学杨磊

这篇文章通过机器学习方法预测未来访问来解决LSM-tree存储引擎下的缓存失效问题,目前该论文已经被数据库顶会VLDB2020接收。

问题背景

传统的缓存替换机制,比如LRU、LFU,在应对传统的以表为粒度的统计和访问信息时,能够维持较好的性能。而在LSM-tree下,这些传统的缓存替换机制不再有效。因为后台的操作(比如flush和compaction)会破坏原有的表粒度的统计信息,也因此破坏了根据统计信息预测访问信息的机制,我们将这个问题称为缓存失效问题(cache invalidation)。当出现这个问题时,LSM-tree存储引擎会发生剧烈的性能抖动,破坏了系统运行的稳定性,同时也极大的影响了用户的访问体验。下图是在X-Engine中对缓存失效问题的测试结果。

究其原因,是因为LSM-tree 使用了能够支持快速写入的 copy-on-write (CoW)方式来存储新增数据。而这种方法不可避免的需要后台操作来帮助它合并数据。因此,我们提出了使用机器学习的方法来实现不被后台操作所影响的高速缓存预取机制。

设计思路

首先我们对缓存失效问题进行形式化定义如下:

根据这个形式化定义,我们发现之所以产生cache invalidation问题,是因为存储引擎中的compaction和flush操作产生的流Mi影响了原有的对block的统计流,从而导致传统的缓存替换机制不再有效。因此我们提出了使用在整体数据流中不会被影响的粒度,也就是key range的粒度作为整体的统计信息采集粒度,并且根据这些统计信息在compaction和flush的过程中使用机器学习方法去预测哪些key range会被访问,从而在他们访问之前提前将系统中对应的数据块预取到缓存中,避免了产生cache invalidation问题。

 

系统架构

我们将设计的系统方案命名为Leaper(Learned Prefetcher的缩写),它是一个可以集成到LSM架构存储引擎内的可插拔系统。主要由三个主要部分组成,如上图所示。下半部分是Learner模块,该模块负责训练不同时间尺度的预测模型,属于离线部分。上半部分是Collector模块用于产生特征化数据,以及Prefetcher模块与存储引擎的flush和compaction操作交互将合适的数据块填充到缓存中。这部分属于在线部分。架构图中的黑色箭头表示数据流,红色箭头表示控制流。接下来阐述每一块的作用:

Learner会从查询日志中提取访问数据,然后将数据转换为训练分类模型的格式。为了减少开销,我们将连续的主键分组为键值范围(key range)。Leaper根据不同的workload选择合适的键值范围大小,以保证良好的模型和系统性能。之后,Learner模块会为Leaper训练多个模型,以预测不同时间尺度下键值范围的未来访问情况。我们使用机器学习中的树模型(GBDT)来进行分类预测以获得最佳的预测效果。

Collector以多线程的方式收集在线访问数据。我们实现了优化的锁机制以减少收集过程的开销。此后,Collector将获得不同键值范围的访问模式并最终将这些访问模式转换成预测模型中可以使用的特征输入。

Prefetcher首先使用Collector提供的特征输入和Learner提供的预测模型来预测键值范围的未来访问情况。根据预测结果,Prefetcher会找出所有参与合并操作的数据块中将要在未来被访问的块。这部分由交叠检查模块处理。最后,Prefetcher将要被访问的块加入缓存以及将不会被访问的块踢出缓存。

关键技术

  • 键值选取

为了获得分类模型的训练数据,我们需要知道数据块的访问信息。但是由于磁盘上数据块随着合并操作而不断变化,我们无法准确知道各个数据块的详细信息。因此,我们引入了键值范围,该范围由一系列连续的键组成,并且在数据库运行期间不会更改。键值范围主要有三个优点。第一,对减少开销很有帮助。第二,键值范围符合数据在底层结构的分布。第三,键值范围非常适合range query。

具体的键值范围选择使用了以下算法,具体步骤及原因可以参考论文,这里不再赘述。

  • 预测模型

综合考虑准确性,效率和可解释性,我们使用梯度提升决策树(GBDT)作为分类模型。它是由许多弱预测模型(决策树)组成的组合模型。GBDT和相关实现(比如XGBoost和LightGBM)在分类预测任务中应用十分广泛。

在模型的特征选择上,除了使用了比较常见的读写特征以及时间戳特征之外,我们还使用了key range的前置key range访问特征来刻画在底层无法得到的业务和应用特征。举个简单的例子,我们在网购时经常会有组合购买的物品(乒乓球和乒乓球拍),这两个商品所对应的key就会有很大概率一起出现在数据库访问中,那么我们使用相似度算法将这两者联系起来,通过某一个商品的访问来预测另一个商品的访问。

  • 锁机制

在多线程存储引擎中,将统计信息采集到Collector中会导致写入冲突。为了防止这种情况,需要应用锁机制。为了能够最大程度得减少开销,我们主要设计了以下三种策略来优化设计。第一,使用双重验证锁和延迟初始化来初始化键值范围。延迟初始化避免了在第一次访问键值范围之前对其进行初始化,并且在执行延迟初始化时使用双重验证锁来减少锁开销。第二,在统计数据过程中使用原子操作来代替互斥锁。第三,使用采样来进一步减少统计开销。由于第一个策略保证了每一个键值范围的第一次访问必定会被采集到,因此采样对于统计信息的影响不会带入到模型预测中。

下表展示了这三种优化策略的应用对于系统性能的影响。全局互斥锁本身会对系统性能产生巨大影响,如果未记录任何统计信息,则平均QPS约为每秒337703。当采用全局互斥锁时,QPS将下降40.61%。但是如果采用上述策略,QPS的下降将减少到3.66%。

  • 交叠检查

在Prefetcher中进行在线推断之后,我们需要确定应该从flush和compaction操作中预取哪些目标数据块。由于Key Range Selection算法生成的键值范围与目标块之间没有一一对应的关系,因此我们需要检查目标块是否包含热键值范围。

我们提出了一个交叠检查的算法,以检查目标块是否将被预取。这个算法结合了二分搜索和归并排序的思想,无论我们在何时得到目标数据块的信息(操作过程中或者操作结束后),都能以更小的代价得到热的数据块。具体算法如下:

  • 回填优化

在compaction过程中,我们引入了两阶段回填来解决compaction过程中回填和剔除缓存数据块的矛盾:为了减少Prefetcher对block cache的影响,Prefetcher会从block cache中剔除旧数据块以节省内存。但是,如果在compaction操作结束之前需要访问那些被剔除的块(请求的记录是旧版本),则会导致新的cache miss。因此我们设计了两阶段回填来解决这个问题。在剔除阶段,预测compaction操作过程中的访问,并剔除不会被访问的块。在第二阶段,预测在compaction操作完成后的一段时间内的访问,回填未来会被访问的块。通过这样的方式既解决了缓存失效的问题,也没有引入新的cache miss。

实验验证

我们分别在天猫买家库订单表、钉钉以及sysbench生成的zipf分布的workload下比较了我们的方法和已有方法。实验结果表明,我们的方法相比于传统方法可以多消除70%以上的cache invalidation,同时能消除几乎所有的latency抖动。更多详细的实验比较结果请关注论文。

论文贡献

  1. 我们形式化定义了cache invalidation问题,并且识别出了在LSM-tree问题中产生这个问题的根本原因。同时我们提出了基于机器学习的高速缓存预取策略来解决这个问题。

  2. 我们在选择机器学习方案时,不仅考虑到模型预测的准确度,同时尽可能降低在离线训练和在线推断方面的开销,使得机器学习模型能够有效的应用在对性能要求较高的OLTP存储引擎中。

  3. 我们将我们的方法和已有方法在多种workload上进行了比较,实验结果表明我们的方法明显优于已有的其他方法。

 

微信号、知乎号、Bilibili“图谱学苑”每周发布最新知识图谱动态,专业知识图谱论文导读,欢迎关注投稿。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值