Ceph中Bufferlist的设计与使用

转自:https://www.ustack.com/blog/bufferlist/

如果非要在整个Ceph中,找出一个类最重要,我觉得非Bufferlist莫属了,原因很简单,因为Bufferlist负责管理Ceph中所有的内存。整个Ceph中所有涉及到内存的操作,无论是msg分配内存接收消息,还是OSD构造各类数据结构的持久化表示(encode/decode),再到实际磁盘操作,都将bufferlist作为基础。

Ceph中bufferlist的设计还是有些复杂的,其中包含三个主要的内buffer::raw(bufferraw)、buffer::ptr(bufferptr)和buffer::list(bufferlist)。这三个类都定义在common/buffer.h中,都是buffer类的内部类,而buffer类本身没有任何内容,只起到了一个命名空间的作用。

这三个类的职责各有不同:
buffer::raw:对应一段真实的物理内存,负责维护这段物理内存的引用计数nref和释放操作。
buffer::ptr:对应Ceph中的一段被使用的内存,也就是某个bufferraw的一部分或者全部。
buffer::list:表示一个ptr的列表(std::list<bufferptr>),相当于将N个ptr构成一个更大的虚拟的连续内存。

buffer这三个类的相互关系可以用下面这个图来表示:

图中蓝色的表示bufferlist,橙色表示bufferptr,绿色表示bufferraw。

在这个图中,实际占用的系统内存一共就三段,分别是raw0,raw1和raw2代表的三段内存。其中:
raw0被ptr0,ptr1,ptr2使用
raw1被ptr3,ptr4,ptr6使用
raw2被ptr5,ptr7使用
而list0是由ptr0-5组成的,list1是由ptr6和ptr7组成的。

从这张图上我们就可以看出bufferlist的设计思路了: 对于bufferlist来说,仅关心一个个ptr。bufferlist将ptr连在一起,当做是一段连续的内存使用。因此,可以通过bufferlist::iterator一个字节一个字节的迭代整个bufferlist中的所有内容,而不需要关心到底有几个ptr,更不用关心这些ptr到底和系统内存是怎么对应的;也可以通过bufferlist::write_file方法直接将bufferlist中的内容出到一个文件中;或者通过bufferlist::write_fd方法将bufferlist中的内容写入到某个fd中。

与bufferlist相对的是负责管理系统内存的bufferraw。bufferraw只关心一件事:维护其所管理的系统内存的引用计数,并且在引用计数减为0时——即没有ptr再使用这块内存时,释放这块内存。

连接bufferlist和bufferraw的是bufferptr。bufferptr关心的是如何使用内存。每一个bufferptr一定有一个bufferraw为其提供系统内存,然后ptr决定使用这块内存的哪一部分。bufferlist只用通过ptr才能对应到系统内存中,而bufferptr而可以独立存在,只是大部分ptr还是为bufferlist服务的,独立的ptr使用的场景并不是很多。

通过引入ptr这样一个中间层次,bufferlist使用内存的方式可以非常灵活,这里可以举两个场景:

1. 快速encode/decode
在Ceph中经常需要将一个bufferlist编码(encode)到另一个bufferlist中,例如在msg发送消息的时候,通常msg拿到的osd等逻辑层传递给它的bufferlist,然后msg还需要给这个bufferlist加上消息头和消息尾,而消息头和消息尾也是用bufferlist表示的。这时候,msg通常会构造一个空的bufferlist,然后将消息头、消息尾、内容都encode到这个空的bufferlist。而bufferlist之间的encode实际只需要做ptr的copy,而不涉及到系统内存的申请和Copy,效率较高。

2. 一次分配,多次使用
我们都知道,调用malloc之类的函数申请内存是非常重量级的操作。利用ptr这个中间层可以缓解这个问题,即我们可以一次性申请一块较大的内存,也就是一个较大的bufferraw,然后每次需要内存的时候,构造一个bufferptr,指向这个bufferraw的不同部分。这样就不再需要向系统申请内存了。最后将这些ptr都加入到一个bufferlist中,就可以形成一个虚拟的连续内存。

关于作者:袁冬博士,UnitedStack产品副总裁,负责UnitedStack产品、售前和对外合作工作;云计算专家,在云计算、虚拟化、分布式系统和企业级应用等方面有丰富的经验;对分布式存储、非结构数据存储和存储虚拟化有深刻地理解,在云存储和企业级存储领域有丰富的研发与实践经验;Ceph等开源存储项目的核心代码贡献者。

时间: 2024-10-10 04:11:47

Ceph中Bufferlist的设计与使用的相关文章

在Ceph中创建虚拟机流程改进之分析

作为个人学习笔记分享,有任何问题欢迎交流! 最近在Gerrit中看到一个change:https://review.openstack.org/#/c/94295/ , 它主要是对当前在Ceph中创建虚拟机的流程的改进.如果glance的backend是ceph, 则nova创建虚拟机到RBD的流程是这样的: 通过glance从ceph中下载image --> 本地 --> 复制image到rbd 这个change的目的就是:不需要下载到本地,直接在rbd中复制image,以提高虚拟机创建的速

看懂此文,不再困惑于 JS 中的事件设计

看懂此文,不再困惑于 JS 中的事件设计 今天刚在关注的微信公众号看到的文章,关于JS事件的,写的很详细也很容易理解,相关的知识点都有总结到,看完就有种很舒畅的感觉,该串起来的知识点都串起来了.反正一字节:爽. 作者:aitangyong 链接:blog.csdn.net/aitangyong/article/details/43231111 抽空学习了下javascript和jquery的事件设计,收获颇大,总结此贴,和大家分享. (一)事件绑定的几种方式 javascript给DOM绑定事件

设计模式中的六大设计原则之三,四

求二叉树的宽度和深度 给定一个二叉树,获取该二叉树的宽度和深度. 例如输入 a / \ b c / \ / \ d e f g 返回3. 详细描述: 接口说明 原型: int GetBiNodeInfo(BiNode &head, unsigned int *pulWidth, unsigned int *pulHeight) 输入参数: head 需要获取深度的二叉树头结点 输出参数(指针指向的内存区域保证有效): pulWidth 宽度 pulHeight 高度 返回值: 0 成功 1 失败

APP中添加标签设计

app设计在视频/图片/文字发布过程中添加标签设计总结 标签,主要是给与用户上传的内容添加标签,这类标签主要有一下几点作用: 1.便于找到相似标签好友,提高产品社交属性: 2.便于归类内容,便于用户和后台进行数据抓取: 3.便于运营相关活动,提升产品互动性: 标签主要是在视频或照片拍摄/编辑结束后,在发布页出现的功能,发布页面具有的通用功能包括:封面(针对视频而言),图片缩略图,标题,描述,地点,标签,@他人,隐私权限,分享/同步到 几项信息,其中按照产品定位的权重及应用本身的属性特质,几点内容

情感设计中与标牌设计相关

在情感设计中与标牌设计相关的,主要是材料的选择,自然的材料往往能迎合大众的情感需求;其次是颜色的选择,一般而言会因人的差异和偏好的不同而不同,但是仍然有一定的规律,有一些光谱之内的色彩易被众人所接受;再是标牌色彩与其图底色彩之间的差别,强烈差异的色彩搭配,是有益于标牌被关注和辨识的,而如果趋向相同则难以被识别和关注,但相对和谐.另外色彩的使用还应关注对野生动物的影响,一般尽量少用视觉反映强烈的红色.标牌的大小也会影响到人的自我意识和反映,如近距离的大标牌(指不可避免的近距离)会给人以压抑,降低个

企业信息化中的管理设计深度探讨研究

管理设计是针对某一类企业进行的,可以说是企业个性化应用的完美体现,但这绝对不是个性化的泛滥.须知任何的企业,其信息化管理是不以管理者的意志为转移的,它不同于经营决策的管理,它必须严格依照基本的管理原理来进行,比如计划方法.订单跟踪.成本核算.预算管理等等,都是严密的信息逻辑支撑的确定性管理方法,只不过由于企业所处行业的不同,所涉及业务有所差异而有所变化而已,这种变化远不足以改变ERP软件的通用性和普遍适用性,而仅仅是要求ERP这个百宝箱中有更多的宝贝而已. 当我们以一种蓦然回首的心态重新审视所从

架构的坑系列:重构过程中的过度设计

架构的坑系列:重构过程中的过度设计 软件架构   2016-06-03 08:47:02 发布 您的评价:       5.0   收藏     2收藏 这个系列是 坑 系列,会说一些在系统设计,系统架构上的 坑 ,这些都是我想到哪说到哪,有像这篇一样比较宏观的 坑 ,后面的文章也会有到具体技术细节的(比如某个函数,某个系统调用) 坑 ,总之,到处都是坑,这些坑有些是我经历过的,有些是听说的,你也可以留言说说你遇到的 坑 . 这一篇,我们从 重构 这个场景来看看系统架构的设计中 过度设计 这个坑

Ceph中的容量计算与管理

转自:https://www.ustack.com/blog/ceph%ef%bc%8drongliang/ 在部署完Ceph集群之后,一般地我们可以通过Ceph df这个命令来查看集群的容量状态,但是Ceph是如何计算和管理的呢?相信大家都比较好奇.因为用过 ceph df这个命令的人都会有这个疑问,它的输出到底是怎么计算的呢?为什么所有pool的可用空间有时候等于GLOBAL中的可用空间,有时候不等呢? 带着这些疑问我们可以通过分析ceph df的实现,来看看Ceph是如何计算容量和管理容量

设计模式中的六大设计原则之一,二

最近在学习设计模式方面的知识,首先接触到的是设计模式中的六大设计原则: 1.单一职责原则: 2.里氏替换原则:3.依赖倒置原则:4.接口隔离原则:5.迪米特法则:开闭原则.下面我来讲讲我对这六大设计自己的理解,如有欠缺地地方,请大家及时指出啊...   1.单一职责原则:应该有且仅有一个原因引起类的变更.通俗的说,即一个类只负责一项职责.下面我们举一个具体的例子来说明一下什么是单一职责原则.电话通话的时候有4个过程发生:拨号,通话,回应,挂机,首先看下面这样一个借口,如图1所示: 图1. 我们来