Ceph 读写流程
本文将梳理Ceph的读写流程,希望帮助希望了解Ceph的人。
概述
Ceph的读写流程是由OSD和PG共同完成的,对于OSD而言,OSD的主要任务是进行消息的接收分发,最终将消息存到队列op_wq中。接下来交由ShardedThreadPool线程池中的线程来处理读写,线程会将请求从op_wq中取出,做如下操作。
- 在ReplicatedPG类中进行一系列的合法性检查。
- 对于读请求,在ReplicatedPG类中完成读请求流程,向client发送ACK消息完成读操作。
- 对于写请求,需要调用ReplicatedPGBackend类,向从副本发送写指令,在从收到所有从副本完成写操作之后,主才会向client发送ACK消息完成写操作。
写操作相对于读操作复杂很多,这是由于Ceph采用副本的高可用机制。一份完整的数据需要存放在多个OSD上面,只有当所有从都确认数据存储到本地,这时候主才可以向client发送写操作成功消息。在[RADOS: A Scalable, Reliable Storage Service for Petabyte-scale Storage Clusters]中对于写消息提出了primary-copy, chain, splay三个副本策略。 Ceph目前(v10.2.10)采用primary-copy策略。如下图所示
osd1是主osd,在第一个RTT收到client写请求时,向从发送写请求,主在RTT3收到osd2和osd3的ack的时候向client发送ack。
具体读写流程:
-
OSD接收消息到消息进入op_wq
如下图所示
ms_fast_dispatch函数是OSD中线程处理client请求的入口函数,接下来进行一系列的调用,进入到op_wq中等待其它线程调用。
-
####op_wq出队列线程调用
ShardedThreadPool线程池会选取线程调用shardedthreadpool_worker函数对入队列的operations进行处理。最终调用ReplicatedPG::do_reequest对于客户端的请求进行分类处理。
-
调用ReplicatedPG::execute_ctx(OpContext *ctx)处理读写
- 对于读请求来说,在execute_ctx()函数中会调用ReplicatedPGBackend类中的函数objects_read_sync读入数据,然后在后续的流程中调用complete_read_ctx()向client回复。
- 对于写请求来说
- 如果log过多,需要整理 log 调用calc_trim_to()
- 调用ReplicatedPGBackend类中issue_op() 向所有从osd发送写请求
- 主处理从的写完成消息,如果所有的从都完成了写请求,调用回调函数ReplicatedPG::eval_repop()向client发送消息完成写操作
下图是写操作的示意图:
图中第二步,主向从发写消息的消息类型是MSG_OSD_REPOP, 第三步从回复的消息类型是MSG_OSD_REPOPREPLY,所带的CEPH_OSD_FLAG_ONDISK标识位为1,表示数据已经写到disk上。
Reference
RADOS: A Scalable, Reliable Storage Service for Petabyte-scale Storage Clusters