转自: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等开源存储项目的核心代码贡献者。

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

  1. Ceph中的序列化

    转自:https://www.ustack.com/blog/cephxuliehua/ 作为主要和磁盘.网络打交道的分布式存储系统,序列化是最基础的功能之一,今天我们来看一下Ceph中序列化的设计与 ...

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

    看懂此文,不再困惑于 JS 中的事件设计 今天刚在关注的微信公众号看到的文章,关于JS事件的,写的很详细也很容易理解,相关的知识点都有总结到,看完就有种很舒畅的感觉,该串起来的知识点都串起来了.反正一 ...

  3. JS 中的事件设计

    看懂此文,不再困惑于 JS 中的事件设计 原文出处: aitangyong    抽空学习了下javascript和jquery的事件设计,收获颇大,总结此贴,和大家分享. (一)事件绑定的几种方式 ...

  4. 推荐一款基于Angular实现的企业级中后台前端/设计解决方案脚手架

    ng-alain 是一个企业级中后台前端/设计解决方案脚手架,我们秉承 Ant Design 的设计价值观,目标也非常简单,希望在Angular上面开发企业后台更简单.更快速.随着『设计者』的不断反馈 ...

  5. Ceph中的容量计算与管理

    转自:https://www.ustack.com/blog/ceph%ef%bc%8drongliang/ 在部署完Ceph集群之后,一般地我们可以通过Ceph df这个命令来查看集群的容量状态,但 ...

  6. mysql中数据库的设计

      软件开发流程(CMMI): 1):项目启动; 2):项目计划: 3):需求分析; 需要得到的结果是什么? 4):系统设计;         该怎么做? 5):系统开发; 6):系统测试; 7):系 ...

  7. ceph中rbd的增量备份和恢复

    ceph中rbd的增量备份和恢复 ceph的文档地址:Ceph Documentation ​ 在调研OpenStack中虚机的备份和恢复时,发现OpenStack和ceph紧密结合,使用ceph做O ...

  8. 在Eclipse中使用WindowBuilder设计Swing程序

    在Eclipse中使用WindowBuilder设计Swing程序     Swing程序表示Java的客户端窗体程序,除了通过手动编写代码的方式设计Swing程序之外,Eclipse中还提供了一种W ...

  9. Java实现图形界面的三部曲及IDE中的窗口设计

    设计和实现图形用户界面的工作主要有以下几点: • (1)创建组件(Component) • 创建组成界面的各种元素,如按钮.文本框等.• (2)指定布局(Layout) • 根据具体需要排列它们的位置 ...

随机推荐

  1. 请听一个故事------>你真的认为iPhone只是一部手机?苹果惊天秘密!!

    在网上看到的一篇小说,感觉有点意思,转载过来大家一起围观下,作者很幽默很风趣. 导读:iPhone的隐藏功能!Jobs的军方身份!图灵服毒自杀的传奇故事!中兴华为的神秘背景! 你真的认为iPhone只 ...

  2. IO多路复用、协程

    一.铺垫:基于socket发送http请求 1.需求一:向百度发送请求搜索关键字“alex”,有如下两种方式: import requests ret = requests.get('https:// ...

  3. 阿里云免费SSL证书申请及配置过程centos7,Nginx

    1:进入购买,等待审核,审核通过后下在一个压缩包 ,里面包含两个文件一个 214979907780888.key 一个214979907780888.pem (如果不在阿里买,也可以在其它平台买,或者 ...

  4. 0107-将Monolith重构为微服务

    重构到微服务的概述 将单一应用程序转换为微服务的过程是应用程序现代化的一种形式.这是开发人员几十年来一直在做的事情.因此,在将应用程序重构为微服务时,我们可以重用一些想法. 一个不使用的策略是重写“B ...

  5. orange安装文档

    一.Orange简介    Orange是一个基于 OpenResty/Nginx 的 API Gateway,提供 API 及 “自定义规则” 的监控和管理,如访问统计.流量切分.AB 测试.API ...

  6. ModelSim之TCL仿真

    在使用ModelSim时,我们一般都是从界面UI进行操作的,这样也比较直观易学.但是在很多的调试时,发现很多操作都是重复的,修改一下代码就要再次进行相关操作,这样很没有效率.其实,ModelSim是可 ...

  7. 剑指offer 面试15题

    面试15题: 题目:二进制中1的个数 题:输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 解题思路一: 最佳方法:把一个整数减去1,再和原整数做“与运算”,会把该整数最右边的1变成0 ...

  8. python面向对象之 封装(Day25)

    封装: 隐藏对象的属性和实现细节,仅对外提供公共访问方式 好处:1.将变化隔离 2.便于使用 3.提高复用性 4.提高安全性 封装原则: 1.将不需要对外提供的内容隐藏起来 2.把属性都隐藏,提供公共 ...

  9. LDA主题模型三连击-入门/理论/代码

    目录 概况 为什么需要 LDA是什么 LDA的应用 gensim应用 数学原理 预备知识 抽取模型 样本生成 代码编写 本文将从三个方面介绍LDA主题模型--整体概况.数学推导.动手实现. 关于LDA ...

  10. Python编程-继承和接口

    一.继承 1.什么是继承 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类. 继承的好处: 可以使用现有类的所有功能,并在无 ...