Ceph源码解析:PG peering(2)

the process of bringing all of the OSDs that store a Placement Group (PG) into agreement about the state of all of the objects (and their metadata) in that PG. Note that agreeing on the state does not mean that they all have the latest contents.

primary PG和raplica PG: 互为副本的三个pg中,有一个主,另外两个为辅;其中为主的称为primary PG,其他两个都称为replica PG。

1、peering过程的影响

故障osd重新上线后,primary PG和replica PG会进入不同的处理流程。primary PG会先进入peering状态,在这个状态的pg暂停处理IO请求,在生产环境中表现为集群部分IO不响应,甚至某些云主机因为等待IO造成应用无法正常处理。下面就peering过程的主要操作结合源码进行分析。

2、peering过程分析

pg是由boost::statechart实现的状态机,peering经历以下主要过程:

         

2

1、GetInfo:

1.1、选取一个epoch区间,对区间内的每个epoch计算其对应的acting set、acting primary、up set、up primary,将相同的结果作为一个interval;

pg->generate_past_intervals();

调用generate_past_intervals()函数,生成past_interval序列。首先确定查找interval的start_epoch(history.last_epoch_clean 上次恢复数据完成的epoch)和end_epoch(history.same_interval_since 最近一次interval的起始epoch)。确定了start_epoch和end_epoch之后,循环这个两个版本间的所有osdmap,确定pg成员变化的区间interval。

1.2、判断每个interval,将up状态的osd加入到prior set;同时将当前的acting set和up set加入到prior set;

pg->build_prior(prior_set);

据past_interval生成prior set集合。确定prior set集合,如果处于当前的acting和up集合中的成员,循环遍历past_interval中的每一个interval,interval.last  >=  info.history.last_epoch_started、! interval.acting.empty()、interval.maybe_went_rw,在该interval中的acting集合中,并且在集群中仍然是up状态的。

1.3、向prior_set中的每个up状态的osd发送Query INFO请求,并等待接收应答,将接收到的请求保存到peer_info中;

context< RecoveryMachine >().send_query(
                peer, pg_query_t(pg_query_t::INFO,
                                it->shard, pg->pg_whoami.shard,
                                pg->info.history,
                                pg->get_osdmap()->get_epoch()));

根据priorset 集合,开始获取集合中的所有osd的info。这里会向所有的osd发送请求info的req(PG::RecoveryState::GetInfo::get_infos())。发送请求后等待回复。

1.4、收到最后一个应答后,状态机post event到GotInfo状态;如果在此期间有一个接收请求的osd down掉,这个PG的状态将持续等待,直到对应的osd恢复;

boost::statechart::result PG::RecoveryState::GetInfo::react(const MNotifyRec &infoevt)

回复处理函数。主要调用了pg->proc_replica_info进行处理:1.将info放入peerinfo数组中。2.合并history记录。 在这里会等待所有的副本都回复info信息。进入下一个状态GetLog。

2、GetLog:

2.1、遍历peer_info,查找best info,将其作为authoritative log;将acting set/peer_info中将处于complete状态的pg以及up set的所有pg存入acting_backfill;

pg->choose_acting(auth_log_shard,
                          &context< Peering >().history_les_bound)

通过pg->choose_acting(auth_log_shard)选择acting集合和auth_osd.

choose_acting中主要进行了两项重要的措施:

find_best_info,查找一个最优的osd。在 find_best_info中查找最优的osd时,判断的条件的优先级有三个:最大的last_update、最小的log_tail、当前的primary。

map<pg_shard_t, pg_info_t>::const_iterator auth_log_shard =
        find_best_info(all_info, history_les_bound);

calc_replicated_acting ,选择参与peering、recovering的osd集合。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/2ae0d15b79dd8c2c7909eb08b0ebc218.html