ceph写流程分析
ceph写流程分析
最近年底了,工作也不太忙了,这几天看看ceph,这几天总结的ceph写流程分析笔记(基于jewel版本>10.2.0),现分享出来,欢迎指点。
rbd到OSD映射关系
客户端使用RBD
设备,使用librbd
、librados
库进行访问管理块设备。
1、创建 一个
pool
,为这个pool
指定pg
的数量,同时在这个pool
中指明保存数据的副本数(通常为3
个副本)。2、在这个
pool
中创建一个rbd
设备rbd0
,那么这个rbd0
都会保存三份,在创建rbd0
时必须指定rbd
的size
,对于这个rbd0
的任何操作不能超过这个size
。3、将这个块设备进行切块,每个块的大小默认为
4M
,并且每个块都有一个名字,名字就是object+
序号。4、将每个
object
通过pg
进行副本位置的分配,pg
会寻找3
个osd
,把这个object
分别保存在这三个osd
上。最后对于object
的存储就变成了存储一个文件rbd0.object1.file
。数据层次映射图如下:
经过pool
,rbd
,object
、pg
的层层映射关系,在PG
这一层中,已经知道存储数据的3
个OSD
所在位置及主从关系。
客户端与primay OSD
建立SOCKET
通信,将要写入的数据传给primary OSD
,由primary OSD
再将数据发送给其他replica OSD
数据节点。
RBD保存形式
如下图所示,Ceph
系统中不同层次的组件/用户所看到的数据的形式是不一样的:
Ceph
客户端所见的是一个完整的连续的二进制数据块,其大小为创建RBD image
是设置的大小或者resize
的大小,客户端可以从头或者从某个位置开始写入二进制数据。librados
负责在RADOS
中创建对象(object
),其大小为pool
的order
决定,默认情况下order = 22
此时object
大小为4MB
;以及负责将客户端传入的二进制块条带化为若干个条带(stripe
)。librados
控制哪个条带由哪个OSD
写入(条带 —写入哪个—->object
—-位于哪个 —->OSD
)
OSD
负责创建在文件系统中创建文件,并将 librados
传入的数据写入数据。
Ceph client
调用librados
创建一个RBD image
,这时候不会做存储空间分配,而是创建若干元数据对象来保存元数据信息。Ceph client
调用librados
开始写数据。librados
计算条带、object
等,然后开始写第一个stripe
到特定的目标object
。librados
根据CRUSH
算法,计算出object
所对应的主OSD ID
,并将二进制数据发给它。主
OSD
负责调用文件系统接口将二进制数据写入磁盘上的文件(每个object
对应一个file,file
的内容是一个或者多个stripe
)。主
ODS
完成数据写入后,它使用CRUSH
算啊计算出第二个OSD
(secondary OSD
)和第三个OSD
(tertiary 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
设备后,这时可以使用librbd
、librados
库进行访问管理块设备。这种方式不会map
到内核,直接调用librbd
提供的接口,可以实现对rbd
设备的访问和管理,但是不会在客户端产生块设备文件。
应用写入rbd
块设备的过程:
- 应用调用
librbd
接口或者对linux
内核虚拟块设备写入二进制块。下面以librbd
为例。 librbd
对二进制块进行分块,默认块大小为4M
,每一块都有名字,成为一个对象librbd
调用librados
将对象写入Ceph
集群librados
向主OSD
写入分好块的二进制数据块 (先建立TCP/IP
连接,然后发送消息给OSD
,OSD
接收后写入其磁盘)- 主
OSD
负责同时向一个或者多个次OSD
写入副本。注意这里是写到日志(Journal
)就返回,因此,使用SSD
作为Journal
的话,可以提高响应速度,做到服务器端对客户端的快速同步返回写结果(ack
)。 - 当主次
OSD
都写入完成后,主OSD
向客户端返回写入成功。 - 当一段时间(也许得几秒钟)后
Journal
中的数据向磁盘写入成功后,Ceph
通过事件通知客户端数据写入磁盘成功(commit
),此时,客户端可以将写缓存中的数据彻底清除掉了。 - 默认地,
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端写操作处理流程
而对于写操作而言,由于要保证数据写入的同步性就会复杂很多:
首先客户端会将数据发送给主osd,
主
osd
同样要先进行写操作预处理,完成后它要发送写消息给其他的从osd
,让他们对副本pg
进行更改,从
osd
通过FileJournal
完成写操作到Journal
中后发送消息告诉主osd
说完成,进入5
当主
osd
收到所有的从osd
完成写操作的消息后,会通过FileJournal
完成自身的写操作到Journal
中。完成后会通知客户端,已经完成了写操作。主
osd
,从osd
的线程开始工作调用Filestore
将Journal
中的数据写入到底层文件系统中。
今天就先总结这么多,总结的不太好,请谅解
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!