概述
OSD是RADOS集群的基本存储单元。
PG(placement group)从名字可理解为放置策略组,它是对象的集合,该集合里的所有对象都具有相同的放置策略:对象的副本都分布在相同的OSD列表上。一个对象只能属于一个PG,一个PG对应于放置在其上的OSD列表。一个OSD上可以分布多个PG。处理来自客户端的读写请求是PG的基本功能。
Pool是整个集群层面定义的一个逻辑的存储池,它规定了数据冗余的类型以及对应的副本分布策略。目前实现了两种pool类型:replicated类型和Erasure Code类型。一个pool由多个PG构成。
读写流程
读写流程大致分为以下几个阶段:
- 客户端基于对象标识中的32位哈希值,通过stable_mod找到存储池中承载该对象的PGID,然后使用该PGID作为CRUSH输入,找到对应PG当前Primary所在的OSD并发送读写请求。
- OSD收到客户端发送的读写请求,将其封装为一个op,并基于其携带的PGID将其转发至对应的PG。
- PG收到op后,完成一些列检查,所有条件均满足后,开始真正执行op。
- 如果op只包含读操作,那么直接执行同步读(对应多副本)或者异步读(对应纠删码),等待读操作完成后由Primary向客户端应答。
- 如果op包含写操作,则由Primary基于op生成一个针对原始对象操作的PG事务,然后将其提交至PGBackend,由后者按照备份策略转化为每个副本真正需要执行的本地事务,并进行分发。当Primary收到所有副本的写入完成应答之后,对应op执行完成,由Primary向客户端回应写入完成。
对象寻址
对象寻址参考client写操作部分。
消息接收与分发
读写请求都是从OSD::ms_fast_dispatch开始,它是接收读写消息message的入口。
消息出队处理
do_request
主要进行PG级别的检查,处理流程:
do_op
主要进行对象级别的检查和一些上下文的准备工作。处理流程:
execute_ctx
prerare_transaction操作主要分为三个阶段:
- 通过do_osd_ops生成原始op对应的PG事务。
- 如果op针对head对象操作通过make_writeable检查是否需要预先执行克隆操作。
- 通过finish_ctx生成操作原始对象的日志,并更新对象的OI和SS属性。
do_osd_ops:
对于读操作,在do_osd_ops()->do_read()中,如果是同步读直接调用pgbackend->objects_read_sync进行读操作。如果是异步读,先将op添加到pending_async_reads中,然后在execute_ctx()检测pending_async_reads队列时执行读操作。
写操作步骤如下:
make_writeable:
如果op针对head对象操作,通过make_writeable检查是否需要预先执行克隆操作。
finish_ctx:
PG事务的内存版本已经准备完毕,此时可以生成原始对象的操作日志,并更新对象上下文中OI与SS属性。