一、OSD模块简介
1.1 消息封装:在OSD上发送和接收信息。
cluster_messenger -与其它OSDs和monitors沟通
client_messenger -与客户端沟通
1.2 消息调度:
Dispatcher类,主要负责消息分类
1.3 工作队列:
1.3.1 OpWQ: 处理ops(从客户端)和sub ops(从其他的OSD)。运行在op_tp线程池。
1.3.2 PeeringWQ: 处理peering任务,运行在op_tp线程池。
1.3.3 CommandWQ:处理cmd命令,运行在command_tp。
1.3.4 RecoveryWQ: 数据修复,运行在recovery_tp。
1.3.5 SnapTrimWQ: 快照相关,运行在disk_tp。
1.3.6 ScrubWQ: scrub,运行在disk_tp。
1.3.7 ScrubFinalizeWQ: scrub,运行在disk_tp。
1.3.8 RepScrubWQ: scrub,运行在disk_tp。
1.3.9 RemoveWQ: 删除旧的pg目录。运行在disk_tp。
1.4 线程池:
有4种OSD线程池:
1.4.1 op_tp: 处理ops和sub ops
1.4.2 recovery_tp:处理修复任务
1.4.3 disk_tp: 处理磁盘密集型任务
1.4.4 command_tp: 处理命令
1.5 主要对象:
ObjectStore *store;
OSDSuperblock superblock; 主要是版本号等信息
OSDMapRef osdmap;
1.6 主要操作流程:
1.6.1 客户端发起请求过程
1.6.2 op_tp线程处理数据读取
1.6.3 对象操作的处理过程
1.6.4 修改操作的处理
1.6.5 日志的写入
1.6.6 写操作处理
1.6.7 事务的sync过程
1.6.8 日志恢复
1.7 整体处理过程图
二、客户端写入数据大致流程及保存形式
2.1 读写框架
2.2 客户端写入流程
在客户端使用 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和磁盘中。
2.3 RBD保存形式
如下图所示,Ceph 系统中不同层次的组件/用户所看到的数据的形式是不一样的: