rbd到OSD映射关系
客户端使用RBD
设备,使用librbd
、librados
库进行访问管理块设备。
pool
,为这个pool
指定pg
的数量,同时在这个pool
中指明保存数据的副本数(通常为3
个副本)。
pool
中创建一个rbd
设备rbd0
,那么这个rbd0
都会保存三份,在创建rbd0
时必须指定rbd
的size
,对于这个rbd0
的任何操作不能超过这个size
。
4M
,并且每个块都有一个名字,名字就是object+
序号。
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
数据节点。
如下图所示,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
,让他们对副本pg
进行更改,
osd
通过FileJournal
完成写操作到Journal
中后发送消息告诉主osd
说完成,进入5
osd
收到所有的从osd
完成写操作的消息后,会通过FileJournal
完成自身的写操作到Journal
中。完成后会通知客户端,已经完成了写操作。
osd
,从osd
的线程开始工作调用Filestore
将Journal
中的数据写入到底层文件系统中。
(adsbygoogle = window.adsbygoogle || []).push({});