【osd】pg_info_t 字段解析

  last_epoch_started介绍

Info中实际保存了两个last_epoch_started属 性,一个位于Info属性之下,另一个则位于Info的history属性之 下。

1. info.last_epoch_started由每个副本收到Primary发送的Peering完成通知之后更新,并与Peering结果一并存盘。

2. info.history.last_epoch_started则由Primary在收到所有副本 Peering完成通知应答之后更新和存盘。由于Primary更新完history 中的last_epoch_started属性之后会同步设置PG为Active状态(注意如果此时Acting中的副本数小于存储池最小副本数,PG将 进入Peered状态), 因此history中last_epoch_started也用于指示PG最近一次开始接受 客户端读写请求时的Epoch。

 

last_epoch_started字段有两个地方出现,一个是pg_info_t结构里的last_epoch_started,代表最后一次Peering成功后的epoch值,是本地PG完成Peering后就设置的。另一个是pg_history_t结构体里的last_epoch_started,是PG里所有的OSD都完成Peering后设置的epoch值。如下图所示:

 

info.last_epoch_started: 记录了PG在interval i完成Peering时的epoch值,在i(包括i)之前的interval提交的所有写操作均会反映到local info/log中,而对于i之后的interval所提交的写操作将不会在当前local info/log中得到体现。由于提交的写操作不可能出现分歧(注:peering已经完成),因此即使用一个更旧的info.last_epoch_started来获取权威log/info信息,也不可能会影响到当前的info.last_epoch_started。

info.history.last_epoch_started: 记录了最近一个interval中,PG作为一个整体完成peering操作后设置的epoch值。由于提交的所有写操作都是由acting set中的OSD提交的,任何无歧义的write操作都会确保acting set中每一个OSD都记录了history.last_epoch_started。

如下我们介绍一下last_epoch_started的更新操作:

1) info.last_epoch_started: PG在本OSD上完成Peering操作,就会马上更新其对应的last_epoch_started的值。参看PG::activate()函数

2) info.history.last_epoch_started: 对于本字段的更新操作,情况较为复杂。


 

 对于PG副本OSD上的info.history.last_epoch_started字段的更新会在Peering完成后马上进行,参看PG::activate();另外还会在Primary OSD向副本OSD发送pg_query_t::INFO时得到更新:

 1 boost::statechart::result PG::RecoveryState::Stray::react(const MQuery& query)
 2 {
 3   PG *pg = context<RecoveryMachine>().pg;
 4   pg->fulfill_query(query, context<RecoveryMachine>().get_recovery_ctx());
 5   return discard_event();
 6 }
 7 
 8 void PG::fulfill_query(const MQuery& query, RecoveryCtx *rctx)
 9 {
10   if (query.query.type == pg_query_t::INFO) 
11   {
12     ...
13     update_history(query.query.history);
14     ...
15   } 
16 }
17 
18 void PG::update_history(const pg_history_t& new_history)
19 {
20   if (info.history.merge(new_history)) 
21   {
22       ...
23   }
24   on_info_history_change(); //scrub机制
25 }
26 
27 bool merge(const pg_history_t &other) 
28 {
29     ...
30     if (last_epoch_started < other.last_epoch_started) {
31       last_epoch_started = other.last_epoch_started;
32       modified = true;
33     }
34     ...
35     return modified;
36 }

 

 1 void PG::activate(ObjectStore::Transaction& t,
 2           epoch_t activation_epoch,
 3           list<Context*>& tfin,
 4           map<int, map<spg_t,pg_query_t> >& query_map,
 5           map<int,
 6               vector<
 7             pair<pg_notify_t,
 8                  pg_interval_map_t> > > *activator_map,
 9                   RecoveryCtx *ctx)
10 {
11     ...
12 
13     // find out when we commit
14     t.register_on_complete(
15         new C_PG_ActivateCommitted(
16             this,
17             get_osdmap()->get_epoch(),
18             activation_epoch));
19 
20     ...
21 }
22 
23 void PG::_activate_committed(epoch_t epoch, epoch_t activation_epoch)
24 {
25     if (pg_has_reset_since(epoch)) {
26         ...
27     } else if (is_primary()) {
28         ...
29         if (peer_activated.size() == actingbackfill.size())
30             all_activated_and_committed();
31     }
32     ...
33 }
34 
35 void PG::all_activated_and_committed()
36 {
37     ...
38     queue_peering_event(
39         CephPeeringEvtRef(
40             std::make_shared<CephPeeringEvt>(
41             get_osdmap()->get_epoch(),
42             get_osdmap()->get_epoch(),
43             AllReplicasActivated())));
44 }
45 
46 boost::statechart::result PG::RecoveryState::Active::react(const AllReplicasActivated &evt){
47     ...
48 
49     // info.last_epoch_started is set during activate()
50     pg->info.history.last_epoch_started = pg->info.last_epoch_started;
51 
52     ...
53 }

 

posted @ 2021-12-23 16:57  苏格拉底的落泪  阅读(382)  评论(0编辑  收藏  举报