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

摘自:https://mp.weixin.qq.com/s/oWujGOLLGItu1Bv5AuO0-A

 2020-09-02 21:45

0.引言

        Ceph是国际知名的开源分布式存储系统,在工业界和学术界都有着重要的影响。Ceph的架构和算法设计发表在国际系统领域顶级会议OSDI、SOSP、SC等上。Ceph社区得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是国际云计算领域应用最广泛的开源分布式存储系统,此外,Ceph也广泛应用在文件、对象等存储领域。Ceph在滴滴也支撑了很多关键业务的运行。在Ceph的大规模部署和使用过程中,我们发现了Ceph的一些性能问题。围绕Ceph的性能优化,我们做了很多深入细致的工作。这篇文章主要介绍我们通过调试分析发现的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%

团队介绍

        滴滴云平台事业群滴滴云存储团队原隶属于滴滴基础平台部,现隶属于新成立的滴滴云事业部。团队承担着公司在线非结构化存储服务的研发,并参与运维工作。具体来说,团队承担了公司内外部业务的绝大部分的对象、块、文件存储需求,数据存储量数十PB。团队技术氛围浓厚,同时具备良好的用户服务意识,立足于用技术创造客户价值,业务上追求极致。团队对于分布式存储、互联网服务架构、Linux存储栈有着深入的理解。

作者介绍

图片

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/74008.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

iOS字体像素与磅的对应关系

注意:低于iOS10的系统,显示的字宽和字高比高于iOS10的系统小。 这就是iOS10系统发布时,很多app显示的内容后面出现…,因而出现很多app为了适配iOS10系统而重新发布新版本。 用PS设计的iOS效果图中,字体是以像素&#x…

运维监控学习笔记7

Zabbix的安装: 1、基础环境准备: 安装zabbix的yum源,阿里的yum源提供了zabbix3.0。 rpm -ivh http://mirrors.aliyun.com/zabbix/zabbix/3.0/rhel/7/x86_64/zabbix-release-3.0-1.el7.noarch.rpm 这个文件就是生成了一个zabbix.repo 2、安…

Rabbitmq延迟消息

目录 一、延迟消息1.基于死信实现延迟消息1.1 消息的TTL(Time To Live)1.2 死信交换机 Dead Letter Exchanges1.3 代码实现 2.基于延迟插件实现延迟消息2.1 插件安装2.2 代码实现 3.基于延迟插件封装消息 一、延迟消息 延迟消息有两种实现方案&#xff…

12-数据结构-数组、矩阵、广义表

数组、矩阵、广义表 目录 数组、矩阵、广义表 一、数组 二.矩阵 三、广义表 一、数组 这一章节理解基本概念即可。数组要看清其实下标是多少,并且二维数组,存取数据,要先看清楚是按照行存还是按列存,按行则是正常一行一行的去读…

汇编知识点之磁盘文件存取技术

1.文件代号式磁盘存取 (1)两个重要的表 (2)简要说明: 文件代号式存取方式将有关文件的各种信息都包括在DOS中。 在处理指定文件时必须使用一个完整的路径名,一旦文件的路径名被送入操作系统,就被赋予一个简单的文件…

第二章:CSS基础进阶-part2:CSS过渡与动画

文章目录 CSS3 过渡动画一、transition属性二、transform属性-2D变换2.1 tanslate : 移动2.2 rotate-旋转2.3 scale-变形2.4 skew-斜切2.5 transform-origin: 变换中心点设置 三、CSS3关键帧动画四、CSS3-3D变换4.1 perspective 定义3D元素距视图距离4.2 transform-…

微服务系列(2)--注册中心

在博文:微服务系列(1)里我们提到过注册中心的概念,简单来说微服务注册中心是一个用于存储和管理微服务实例信息的组件,它提供了服务注册、服务发现、服务健康检查等功能,以确保微服务之间的稳定通信。在微服务架构中,各…

工程监测振弦采集仪采集到的数据如何进行分析和处理

工程监测振弦采集仪采集到的数据如何进行分析和处理 振弦采集仪是一个用于测量和记录物体振动的设备。它通过测量物体表面的振动来提取振动信号数据,然后将其转换为数字信号,以便进行分析和处理。在实际应用中,振弦采集仪是广泛应用于机械、建…

C#软件外包开发流程

C# 是一种由微软开发的多范式编程语言,常用于开发各种类型的应用程序,从桌面应用程序到移动应用程序和Web应用程序。下面和大家分享 C# 编程学习流程,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司&#…

深度学习笔记(kaggle课程《Intro to Deep Learning》)

一、什么是深度学习? 深度学习是一种机器学习方法,通过构建和训练深层神经网络来处理和理解数据。它模仿人脑神经系统的工作方式,通过多层次的神经网络结构来学习和提取数据的特征。深度学习在图像识别、语音识别、自然语言处理等领域取得了…

通过代码实现窗口界面布局的方法

在QWidget窗口中添加相关事件resizeEvent()函数并编写相关功能代码: void Widget::resizeEvent(QResizeEvent *event) {QSize szui->plainTextEdit->size();ui->plainTextEdit->move(5,5);ui->pabpic->move(5,sz.height()5);ui->plainTextEd…

上传excel文件

文件上传&#xff0c;其实就是用el-upload组件来实现上传&#xff0c;只是换了样式&#xff0c;和图片上传一样 <el-form-item label"选择文件"><el-input placeholder"请选择文件" v-model"form.file" disabled style"width: 45…

Android T 窗口层级其二 —— 层级结构树的构建(更新中)

如何通过dump中的内容找到对应的代码&#xff1f; 我们dump窗口层级发现会有很多信息&#xff0c;adb shell dumpsys activity containers 这里我们以其中的DefaultTaskDisplayArea为例 在源码的framework目录下查找该字符串&#xff0c;找到对应的代码就可以通过打印堆栈或者…

vue.draggable浅尝

介绍 Vue.Draggable是一款基于Sortable.js实现的vue拖拽插件。支持移动设备、拖拽和选择文本、智能滚动&#xff0c;可以在不同列表间拖拽、不依赖jQuery为基础、vue 2过渡动画兼容、支持撤销操作&#xff0c;总之是一款非常优秀的vue拖拽组件。本篇将介绍如何搭建环境及简单的…

Python爬虫之解决浏览器等待与代理隧道问题

作为专业爬虫程序员&#xff0c;我们往往需要应对一些限制性挑战&#xff0c;比如浏览器等待和使用代理隧道。在Python爬虫开发中&#xff0c;这些问题可能会导致我们的爬虫受阻。本文将为你分享解决这些问题的方案&#xff0c;帮助你顺利应对浏览器等待和代理隧道的挑战&#…

jeecg-boot批量导入问题注意事项

现象&#xff1a; 由于批量导入数据速度很快&#xff0c; 因为数据库中的create time字段的时间可能一样&#xff0c;并且jeecg框架自带的是根据生成时间排序&#xff0c; 因此在前端翻页查询的时候&#xff0c;数据每次排序可能会不一样&#xff0c; 会出现第一页已经出现过一…

分类预测 | MATLAB实现BO-BiGRU贝叶斯优化双向门控循环单元多输入分类预测

分类预测 | MATLAB实现BO-BiGRU贝叶斯优化双向门控循环单元多输入分类预测 目录 分类预测 | MATLAB实现BO-BiGRU贝叶斯优化双向门控循环单元多输入分类预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.Matlab实现BO-BiGRU贝叶斯优化双向门控循环单元多特征分…

dirsearch_暴力扫描网页结构

python3 dirsearch 暴力扫描网页结构&#xff08;包括网页中的目录和文件&#xff09; 下载地址&#xff1a;https://gitee.com/xiaozhu2022/dirsearch/repository/archive/master.zip 下载解压后&#xff0c;在dirsearch.py文件窗口&#xff0c;打开终端&#xff08;任务栏…

Linux命名管道进程通信

文章目录 前言一、什么是命名管道通信二、创建方式三、代码示例四、文件进程通信总结 前言 命名管道 是实现进程间通信的强大工具&#xff0c;它提供了一种简单而有效的方式&#xff0c;允许不同进程之间进行可靠的数据交换。不仅可以在同一主机上的不相关进程间进行通信&…

2023年国赛数学建模思路 - 复盘:光照强度计算的优化模型

文章目录 0 赛题思路1 问题要求2 假设约定3 符号约定4 建立模型5 模型求解6 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 问题要求 现在已知一个教室长为15米&#xff0c;宽为12米&…