ceph写流程分析

ceph写流程分析

最近年底了,工作也不太忙了,这几天看看ceph,这几天总结的ceph写流程分析笔记(基于jewel版本>10.2.0),现分享出来,欢迎指点。

rbd到OSD映射关系

客户端使用RBD设备,使用librbdlibrados库进行访问管理块设备。

  • 1、创建 一个pool,为这个pool指定pg的数量,同时在这个pool中指明保存数据的副本数(通常为3个副本)。

  • 2、在这个pool中创建一个rbd设备rbd0,那么这个rbd0都会保存三份,在创建rbd0时必须指定rbdsize,对于这个rbd0的任何操作不能超过这个size

  • 3、将这个块设备进行切块,每个块的大小默认为4M,并且每个块都有一个名字,名字就是object+序号。

  • 4、将每个object通过pg进行副本位置的分配,pg会寻找3osd,把这个object分别保存在这三个osd上。最后对于object的存储就变成了存储一个文件 rbd0.object1.file。数据层次映射图如下:

经过poolrbdobjectpg的层层映射关系,在PG这一层中,已经知道存储数据的3OSD所在位置及主从关系。
客户端与primay OSD建立SOCKET 通信,将要写入的数据传给primary OSD,由primary OSD再将数据发送给其他replica OSD数据节点。

RBD保存形式

如下图所示,Ceph 系统中不同层次的组件/用户所看到的数据的形式是不一样的:

  • Ceph 客户端所见的是一个完整的连续的二进制数据块,其大小为创建 RBD image 是设置的大小或者 resize 的大小,客户端可以从头或者从某个位置开始写入二进制数据。
  • librados 负责在 RADOS 中创建对象(object),其大小为 poolorder 决定,默认情况下 order = 22 此时 object 大小为 4MB;以及负责将客户端传入的二进制块条带化为若干个条带(stripe)。
  • librados 控制哪个条带由哪个 OSD 写入(条带 —写入哪个—-> object —-位于哪个 —-> OSD

OSD 负责创建在文件系统中创建文件,并将 librados 传入的数据写入数据。

  1. Ceph client 调用 librados 创建一个 RBD image,这时候不会做存储空间分配,而是创建若干元数据对象来保存元数据信息。

  2. Ceph client 调用 librados 开始写数据。librados 计算条带、object 等,然后开始写第一个 stripe 到特定的目标 object

  3. librados 根据 CRUSH 算法,计算出 object 所对应的主 OSD ID,并将二进制数据发给它。

  4. OSD 负责调用文件系统接口将二进制数据写入磁盘上的文件(每个 object 对应一个 file,file 的内容是一个或者多个 stripe)。

  5. ODS 完成数据写入后,它使用 CRUSH 算啊计算出第二个OSDsecondary OSD)和第三个OSDtertiary OSD)的位置,然后向这两个 OSD 拷贝对象。都完成后,它向 ceph client反馈该 object 保存完毕。

    Ceph client 向一个 RBD image 写入二进制数据(假设 pool 的拷贝份数为 3)

客户的写流程操作

在客户端使用 rbd 时一般有两种方法:

  • 第一种 是 Kernel rbd。就是创建了rbd设备后,把rbd设备map到内核中,形成一个虚拟的块设备,这时这个块设备同其他通用块设备一样,一般的设备文件为/dev/rbd0,后续直接使用这个块设备文件就可以了,可以把 /dev/rbd0 格式化后 mount 到某个目录,也可以直接作为裸设备使用。这时对rbd设备的操作都通过kernel rbd操作方法进行的。
  • 第二种是 librbd 方式。就是创建了rbd设备后,这时可以使用librbdlibrados库进行访问管理块设备。这种方式不会map到内核,直接调用librbd提供的接口,可以实现对rbd设备的访问和管理,但是不会在客户端产生块设备文件。

应用写入rbd块设备的过程:

  1. 应用调用 librbd 接口或者对linux 内核虚拟块设备写入二进制块。下面以 librbd 为例。
  2. librbd 对二进制块进行分块,默认块大小为 4M,每一块都有名字,成为一个对象
  3. librbd 调用 librados 将对象写入 Ceph 集群
  4. librados 向主 OSD 写入分好块的二进制数据块 (先建立TCP/IP连接,然后发送消息给 OSDOSD 接收后写入其磁盘)
  5. OSD 负责同时向一个或者多个次 OSD 写入副本。注意这里是写到日志(Journal)就返回,因此,使用SSD作为Journal的话,可以提高响应速度,做到服务器端对客户端的快速同步返回写结果(ack)。
  6. 当主次OSD都写入完成后,主 OSD 向客户端返回写入成功。
  7. 当一段时间(也许得几秒钟)后Journal 中的数据向磁盘写入成功后,Ceph通过事件通知客户端数据写入磁盘成功(commit),此时,客户端可以将写缓存中的数据彻底清除掉了。
  8. 默认地,Ceph 客户端会缓存写入的数据直到收到集群的commit通知。如果此阶段内(在写方法返回到收到commit通知之间)OSD 出故障导致数据写入文件系统失败,Ceph 将会允许客户端重做尚未提交的操作(replay)。因此,PG 有个状态叫 replay:“The placement group is waiting for clients to replay operations after an OSD crashed.”

    也就是,文件系统负责文件处理,librbd 负责块处理,librados 负责对象处理,OSD 负责将数据写入在Journal和磁盘中。

osd端写操作处理流程

而对于写操作而言,由于要保证数据写入的同步性就会复杂很多:

  1. 首先客户端会将数据发送给主osd,

  2. osd同样要先进行写操作预处理,完成后它要发送写消息给其他的从osd,让他们对副本pg进行更改,

  3. osd通过FileJournal完成写操作到Journal中后发送消息告诉主osd说完成,进入5

  4. 当主osd收到所有的从osd完成写操作的消息后,会通过FileJournal完成自身的写操作到Journal中。完成后会通知客户端,已经完成了写操作。

  5. osd,从osd的线程开始工作调用FilestoreJournal中的数据写入到底层文件系统中。

今天就先总结这么多,总结的不太好,请谅解


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!