NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

滴滴 Ceph 分布式存储系统优化之锁优化

  • 2020-09-08
  • 本文字数:3508 字

    阅读完需:约 12 分钟

滴滴Ceph分布式存储系统优化之锁优化

1. 背景

在支撑一些延迟敏感的在线应用过程中,我们发现 Ceph 的尾延迟较差,当应用并发负载较高时,Ceph 很容易出现延迟的毛刺,对延迟敏感的应用造成超时甚至崩溃。我们对 Ceph 的尾延迟问题进行了深入细致的分析和优化。造成尾延迟的一个重要原因就是代码中锁的使用问题,下面根据锁问题的类型分别介绍我们的优化工作。本文假设读者已熟悉 Ceph 的基本读写代码流程,代码的版本为 Luminous。

2. 持锁时间过长

2.1 异步读优化

Ceph 的 osd 处理客户端请求的线程池为 osd_op_tp,在处理操作请求的时候,线程会先锁住操作对应 pg 的 lock。其中,处理对象读请求的代码如下图所示,在锁住对象所属 pg 的 lock 后,对于最常用的多副本存储方式,线程会同步进行读操作,直到给客户端发送返回的数据后,才会释放 pg lock。


在进行读操作时,如果数据没有命中 page cache 而需要从磁盘读,是一个耗时的操作,并且 pg lock 是一个相对粗粒度的锁,在 pg lock 持有期间,其它同属一个 pg 的对象的读写操作都会在加锁上等待,增大了读写延迟,降低了吞吐率。同步读的另一个缺点是读操作没有参与流量控制。



我们对线上集群日志的分析也验证了上述问题,例如,一个日志片段如下图所示,图中列举了两个 op 的详细耗时信息,这两个 op 均为同一个 osd 的线程所执行,且操作的是同一个 pg 的对象。根据时间顺序,第一个 op 为 read,总耗时为 56ms。第二个 op 为 write,总耗时为 69ms。图中信息显示,第二个 op 处理的一个中间过程,即副本写的完成消息在处理之前,在 osd 请求队列中等待了 36ms。结合上图的代码可以知道,这 36ms 都是耗在等待 pg lock 上,因为前一个 read 操作持有 pg lock,而两个对象属于相同 pg。



我们的优化如下图所示,我们创建了独立的读线程,负责处理读请求,osd_op_tp 线程只需将读请求提交到读线程的队列即可返回解锁,大大减少了 pg lock 的持有时间。读线程完成磁盘读之后,将结果放到 finisher 线程的队列,finisher 线程重新申请 pg lock 后负责后续处理,这样将耗时的磁盘访问放在了不持有 pg lock 的流程中,结合我们在流量控制所做的优化,读写操作可以在统一的框架下进行流量控制,从而精准控制磁盘的利用率,以免磁盘访问拥塞造成尾延迟。



我们用 fio 进行了异步读优化效果的测试,测试方法:对同一个 pool 的两个 rbd,一个做随机读,另一个同时做随机写操作,将 pg number 配置为 1,这样所有对象读写会落到同一个 osd 的同一个 pg。异步读优化后,随机写平均延迟下降了 53% 。下图为某业务的 filestore 集群异步读上线前后读吞吐率的数据,箭头所指为上线时间,可见上线之后,集群承载的读操作的吞吐率增加了 120%



上述优化在使用 filestore 存储后端时取得了明显的效果,但在使用 bluestore 存储后端时,bluestore 代码中还存在持有 pg 粒度锁同步读的问题,具体见 BlueStore::read 的代码。我们对 bluestore 的读也进行了异步的优化,这里就不详细介绍了。

3. 锁粒度过粗

3.1 object cache lock 优化

Ceph 在客户端实现了一个基于内存的 object cache,供 rbd 和 cephfs 使用。但 cache 只有一把大的互斥锁,任何 cache 中对象的读写都需要先获得这把锁。在使用写回模式时,cache flusher 线程在写回脏数据之前,也会锁住这个锁。这时对 cache 中缓存对象的读写都会因为获取锁而卡住,使读写延迟增加,限制了吞吐率。


我们实现了细粒度的对象粒度的锁,在进行对象的读写操作时,只需获取对应的对象锁,无需获取全局锁。只有访问全局数据结构时,才需要获取全局锁,大大增加了对象间操作的并行。并且对象锁采用读写锁,增加了同一对象上读的并行。测试表明,高并发下 rbd 的吞吐率增加了超过 20%

4. 不必要的锁竞争

4.1 减少 pg lock 竞争

Ceph 的 osd 对客户端请求的处理流程为,messenger 线程收到请求后,将请求放入 osd_op_tp 线程池的缓存队列。osd_op_tp 线程池的线程从请求缓存队列中出队一个请求,然后根据该请求操作的对象对应的 pg 将请求放入一个与 pg 一一对应的 pg slot 队列的尾部。然后获取该 pg 的 pg lock,从 pg slot 队列首部出队一个元素处理。


可见,如果 osd_op_tp 线程池的请求缓存队列中连续两个请求操作的对象属于相同的 pg,则一个 osd_op_tp 线程出队前一个请求加入 pg slot 队列后,获取 pg lock,从 pg slot 队列首部出队一个请求开始处理。另一个 osd_op_tp 线程从请求缓存队列出队第二个请求,因为两个请求是对应相同的 pg,则它会加入相同的 pg slot 队列,然后,第二个线程在获取 pg lock 时会阻塞。这降低了 osd_op_tp 线程池的吞吐率,增加了请求的延迟。


我们的优化方式是保证任意时刻每个 pg slot 队列只有一个线程处理。因为在处理 pg slot 队列中的请求之前需要获取 pg lock,因此同一个 pg slot 队列的请求是无法并行处理的。我们在每个 pg slot 队列增加一个标记,记录当前正在处理该 pg slot 的请求的线程。当有线程正在处理一个 pg slot 的请求时,别的线程会跳过处理该 pg slot,继续从 osd_op_tp 线程池的请求缓存队列出队请求。

4.2 log lock 优化

Ceph 的日志系统实现是有一个全局的日志缓存队列,由一个全局锁保护,由专门的日志线程从日志缓存队列中取日志打印。工作线程提交日志时,需要获取全局锁。日志线程在获取日志打印之前,也需要获取全局锁,然后做一个交换将队列中的日志交换到一个临时队列。另外,当日志缓存队列长度超过阈值时,提交日志的工作线程需要睡眠等待日志线程打印一些日志后,再提交。锁的争抢和等待都增加了工作线程的延迟。


我们为每个日志提交线程引入一个线程局部日志缓存队列,该队列为经典的单生产者单消费者无锁队列。线程提交日志直接提交到自己的局部日志缓存队列,该过程是无锁的。只有队列中的日志数超过阈值后,才会通知日志线程。日志线程也会定期轮询各个日志提交线程的局部日志缓存队列,打印一些日志,该过程也是无锁的。通过上述优化,基本避免了日志提交过程中因为锁竞争造成的等待,降低了日志的提交延迟。测试在高并发日志提交时,日志的提交延迟可降低接近 90%

4.3 filestore apply lock 优化

对于 Ceph filestore 存储引擎,同一个 pg 的 op 需要串行 apply。每个 pg 有一个 OpSequencer(简称 osr),用于控制 apply 顺序,每个 osr 有一个 apply lock 以及一个 op 队列。对于每个待 apply 的 op,首先加入对应 pg 的 osr 的队列,然后把 osr 加到 filestore 的负责 apply 的线程池 op_tp 的队列,简称为 apply 队列。op_tp 线程从 apply 队列中取出一个 osr,加上它的 apply lock,再从 osr 的队列里取出一个 op apply,逻辑代码如下图左所示。可见,每个 op 都会把其对应的 osr 加入到 apply 队列一次。如果多个 op 是针对同一个 pg 的对象,则这个 pg 的 osr 可能多次加入到 apply 队列。如果 apply 队列中连续两个 osr 是同一个 pg 的,也就是同一个 osr,则前一个 op 被一个线程进行 apply 时,osr 的 apply lock 已经加锁,另一个线程会在该 osr 的 apply lock 上阻塞等待,降低了并发度。



这个问题也体现在日志中。一个线上集群日志片段如下图,有两个 op_tp 线程 6700 和 5700,apply 队列里三个对象依次来自 pg: 1.1833, 1.1833. 1.5f2。线程 6700 先拿到第一个对象进行 apply, 线程 5700 拿第二个对象进行 apply 时卡在 apply lock 上,因为两个对象都来自 pg 1.1833,直到 6700 做完才开始 apply。而 6700 拿到第三个对象,即 1.5f2 的对象进行 apply 即写 page cache 只用了不到 1ms,但实际 apply 延迟 234ms,可见第三个对象在队列里等待了 233ms。如果 5700 不用等待 apply lock,则第二和第三个对象的 apply 延迟可以大大缩短。



我们优化后的逻辑代码如上图右所示,同一个 osr 只加入 apply 队列一次,取消 apply lock,利用原子操作实现无锁算法。上面的算法可以进一步优化,在将一个 osr 出队之后,可以一次从它的队列中取 m(m>1)个 op 进行 apply,在 op apply 完成阶段,改为如果 atomic::fetch_sub(osr->queue_length, m) > m,则将 osr 重新入队以提高吞吐率。


我们用 fio 进行了 apply lock 优化效果测试,方法为建两个 pool,每个 pool 的 pg number 为 1,每个 pool 一个 rbd, 对两个 rbd 同时进行随机写的操作,一个 pool 写入数据的量为 31k*10k,另一个 pool 写入数据的量为 4k*100k, 衡量所有请求 apply 的总耗时。优化前总耗时 434ks, 优化后总耗时 45ks,减少 89.6%


作者介绍


汪黎,滴滴首席工程师


负责滴滴在线非结构化存储研发,曾任国防科技大学计算机学院副研究员,教研室主任,天河云存储负责人


本文转载自公众号滴滴技术(ID:didi_tech)。


原文链接


滴滴Ceph分布式存储系统优化之锁优化


2020-09-08 10:082114

评论

发布
暂无评论
发现更多内容

Gson 解析 Json 容错才是关键,举几个常用的实例!,android开发视频百度网盘

android 程序员 移动开发

Hook 技术初探,【2021Android最新学习路线

android 程序员 移动开发

Kubernetes + 焱融 SaaS 数据服务平台,个性化需求支持就没输过

焱融科技

云计算 分布式 高性能 公有云 文件存储

Google禁止Android-11-自定义-Toast-了?,android开发实战数据

android 程序员 移动开发

Java泛型,安卓面试项目经验

android 程序员 移动开发

Fresco实践总结,阿里P7大牛亲自教你

android 程序员 移动开发

GitHub 上优质项目整理,推荐一个GitHub项目

android 程序员 移动开发

如何实现高效运维?来谈谈性能优化那些事(含直播回顾 Q&A)

墨天轮

oracle 性能优化

GitHub标星3-5K+【Android校招面试指南,flutter中文本框的长度

android 程序员 移动开发

Handler源码分析之二 异步消息的处理,2021金三银四面试季

android 程序员 移动开发

HTTPS详解,谈谈我认为的高级Android开发到底应该是怎样的

android 程序员 移动开发

Groovy脚本基础全攻略,重磅

android 程序员 移动开发

IOC架构设计之Dagger2架构设计(三),进阶加薪全靠它

android 程序员 移动开发

IOC架构设计之控制反转和依赖注入(一),2021大厂Android面试经验

android 程序员 移动开发

万字解读鸿蒙轻内核物理内存模块

华为云开发者联盟

鸿蒙 内存 虚拟内存 物料内存 内存页

Gbox开源:比RN和WebView更轻的高性能动态化业务容器,解决首页动态化的痛点

android 程序员 移动开发

GitHub标星3,Android面试

android 程序员 移动开发

GitHub标星9K的Google官方MVP+Rxjava项目详解,靠这份资料我从6K变成了40K

android 程序员 移动开发

IT圈的“年龄歧视”,移动互联网app开发实例

android 程序员 移动开发

HashMap 源码解析二、put 相关函数,android原生开发教程

android 程序员 移动开发

Framework掌握不熟?字节跳动大牛带你系统化学习,小白以及计算机类学生的福音

android 程序员 移动开发

Git各指令的本质,真是通俗易懂啊,h5移动端开发进行定位

android 程序员 移动开发

Gradle多维度使用,h5开发移动端

android 程序员 移动开发

移动端1px解决方案

CRMEB

Glide源码学习五:回调与监听,Android快速转战Kotlin教程

android 程序员 移动开发

IT-架构师绝对不能错过的-34-技术知识图谱帮你轻松拿下大厂offer

android 程序员 移动开发

🍃【Spring专题】「实战系列」重新回顾一下Spring框架的异步执行调用的原理和实战

洛神灬殇

spring 异步编程 异步调度 11月日更

javascript中的原型与对象(一),12个View绘制流程高频面试题

android 程序员 移动开发

GDP大跳水,“溢价阶层,kotlinandroid开发教程

android 程序员 移动开发

GitHub标星3(1),腾讯Android开发面试记录

android 程序员 移动开发

恒源云(GPUSHARE)_云GPU服务器如何使用Tmux?

恒源云

深度学习

滴滴Ceph分布式存储系统优化之锁优化_数据库_滴滴技术_InfoQ精选文章