入选数据库顶会 VLDB:如何有效降低产品级内存数据库快照尾延迟?

阿里云与上海交通大学合作的论文提出的Async-fork技术解决了内存键值对数据库(如Redis)在使用fork做快照时造成的查询延迟问题。Async-fork通过将页表拷贝从父进程移至子进程,减少了快照期间的内核态时间,降低了快照请求的尾延迟。实验表明,相比默认fork,Async-fork在8GB和64GB实例中分别减少了81.76%和99.84%的p99延迟。
摘要由CSDN通过智能技术生成

阿里云操作系统团队、阿里云数据库团队以及上海交通大学新兴并行计算研究中心一起合作的论文 “Async-fork: Mitigating Query Latency Spikes Incurred by the Fork-based Snapshot Mechanism from the OS Level” 被数据库系统领域顶会 Very Large Data Bases Conferences (VLDB)录用为长论文。VLDB 从 1975 年开始举办,属于计算机数据库系统领域顶级会议(CCF A 类),平均录用率为 18.6%。

摘要

得益于超快的查询速度,内存键值对数据库(In-memory key-value store, 下称 IMKVS)被广泛使用于延迟敏感的在线应用程序中。

为了支持数据持久化,流行的 IMKVS(例如 Redis 与 KeyDB)使用系统调用 fork 定期获取内存数据的快照。然而,这种基于 fork 的快照机制可能会引发在快照生成期间到达的查询延迟大幅增加,进而影响在线程序的服务质量。这是因为 IMKVS 引擎在调用 fork 期间陷入内核态,为了保证数据的一致性,在此期间无法处理用户查询请求。而当 IMKVS 内存占用较大时,fork 调用过程耗时非常长。

为此,我们优化了 fork,这可以在不修改 IMKVS 的基础上,解决快照期间查询延迟大幅增加的问题。

具体而言,我们设计了一个新的 fork(称为 Async-fork),将 fork 调用过程中最耗时的页表拷贝部分从父进程移动到子进程,父进程因而可以快速返回用户态处理用户查询,子进程则在此期间完成页表拷贝。为了保持父子进程之间的数据一致性,我们设计了一套高效的主动同步机制。实验结果表明,与 Linux 中的默认 fork 相比,Async-fork 显著减少了快照期间到达请求的尾延迟(在 8GB IMKVS 实例上,p99 延迟减少了 81.76%;在 64GB 的实例上 p99 延迟减少了 99.84%)。

问题介绍

对于 IMKVS 而言,由于所有数据都驻留在内存中,数据持久化是实现数据备份与容灾的关键功能。流行的 IMKVS(Redis 与 KeyDB)实现数据持久化的方式是使用系统调用 fork 获取内存中数据在某时间点上的快照,并将快照转储到硬盘中。

如图 1(a)所示,父进程调用 fork 创建子进程,而子进程保有与父进程在调用 fork 的时刻相同的数据。随后,子进程在后台将数据写入硬盘,而父进程则继续处理用户的查询请求。尽管这样的快照机制已经将繁重的 IO 任务从父进程委派给子进程,但仍然可能导致在 fork 调用期间到达的请求的延迟激增(例如,图 1(a)中在 T0 时刻到达的请求)。

这是因为父进程在调用 fork 期间陷入内核态,无法处理用户查询请求。因为 fork 调用的耗时随进程内存的占用增大而增大,延迟激增的现象随 IMKVS 内存占用的增大而变得更为严重。实验表明,在 64GB 的 Redis 实例上,非快照期间请求的 p99 延迟与最大延迟分别为 0.08ms 与 6.46ms,而在快照期间请求的 p99 延迟与最大延迟分别为 911.95ms 与 1204.78ms。

图 1:The workflow of the parent and child process with(a)default fork,(b)shared page table(SPT)-based fork,(c)the proposed Async-fork in the snapshot procedure.

在默认 fork 的调用过程中,父进程需要将许多进程元数据(例如文件描述符、信号量、页表等)复制到子进程,而页表的复制是其中最耗时的部分(占据 fork 调用耗时的 97% 以上)。先前的研究者提出了基于共享页表的 fork 优化方法,这种方法建议以写时复制(Copy-on-write, 下称 CoW)的方式在父子进程之间共享页表。

如图 1(b)所示,在共享页表方案中,页表复制不在 fork 调用期间进行,而是在将来发生修改时再进行复制。虽然共享页表能够很大程度上解决延迟激增问题,但我们的分析表明这样的设计在 IMKVS 中导致父进程从 fork 调用中返回用户态后频繁中断陷入内核态完成页表复制,对性能造成了不利影响。此外,共享页表还引入了数据泄漏漏洞,这个漏洞可能导致子进程持有与父进程不一致的数据,破坏了快照一致性。因此,共享页表方法不适用于解决延迟激增问题。

Async-fork 的核心思想与挑战

我们提出了另一种 fork 的优化方法(称为 Async-fork),总体设计思路如图 1(c)所示。Async-fork 设计的核心思想是将复制页表的工作从父进程转移到子进程。这可以缩短父进程调用 fork 时陷入内核态的时间,能够尽快返回用户态处理用户的查询请求,从而解决延迟激增问题;另一方面,还确保了父进程和子进程都具有独占页表,从而避免引入数据泄漏漏洞。

然而,实现上述设计并非易事。如图 2 所示,我们面临的首要挑战是页表的异步操作可能导致快照不一致。以图 2 中的①为例,IMKVS 在 T0 时刻拍摄快照,而某个用户请求在 T2 时刻向 IMKVS 插入了新的键值对(k2, v2),这导致父进程修改它的页表项(PTE2)。当这个被修改的页表项尚未被子进程复制时,新插入的键值对将被子进程最终写入硬盘,破坏了快照一致性。因此,我们在 Async-fork 中设计了一种主动同步机制,使父进程在修改页表项前,主动将被修改的页表项复制到子进程。

实际上,除了用户请求可能导致页表项修改外,操作系统中的许多内存操作都会引起页表项修改。例如,操作系统会定期在 NUMA 节点之间迁移页面,导致涉及的页表项被修改为不可访

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值