本文从源代码出发,分析产生pg_temp的场景,及其要解决的问题、
1. pg_temp的产生
1.1 pg_temp请求的发送
在OSD::process_peering_events()函数的最后会调用OSDService::send_pg_temp()来发送MSG_OSD_PGTEMP请求到OSDMonitor,如下:
由上述代码可知,send_pg_temp()函数会对pg_temp_wanted中的PG打包成一个MOSDPGTemp请求,发送到OSDMonitor:
_sent_pg_temp()函数将已经发送过MOSDPGTemp请求的PG加入到pg_temp_pending中,同时清空pg_temp_wanted。
此外,通过代码上下文我们知道是通过调用queue_want_pg_temp()来向pg_temp_wanted中来添加数据的:
1.2 pg_temp产生的场景
查询OSDService::queue_want_pg_temp()的调用,我们发现主要有如下两个地方调用:
1.2.1 函数choose_acting()
由上面代码,产生pg_temp的场景有:
注: 当前PG最新的up set、acting set已经在PG::init_primary_up_acting()函数中计算得到,最原始是在OSD::advance_pg()计算得到然后通过AdvMap事件传递过来
对于第一种情况,通常是由于backfill不完整导致的。此时如果up set与acting set不一致,则进入WaitActingChange状态,否则进入InComplete状态。
对于第二种情况,我们先来看一下PG::calc_replicated_acting()函数:
want的计算方式如下:
1) 计算want_primary
如果up set非空,并且up_primary当前处于complete状态,且其pg log日志与权威日志有重叠,那么就将up_primary赋值给want_primary,否则就将拥有权威日志的osd赋值给want_primary.
2) 遍历up set列表,如果对应的副本是complete状态,且与want_primary或auth_log_shard有日志重叠,则将该副本osd加入到want;
3)遍历acting列表,如果对应的副本是complete状态,且与want_primary有日志重叠,则将该副本osd加入到want;
4) 遍历该PG获取到的所有pg info,如果对应的副本是complete状态,且与want_primary有日志重叠,则将该副本加入到want
综上,这里求出的want列表中的元素基本是要能够通过日志来进行恢复的,而acting列表中可能还包括一些要backfill的OSD。
针对第二种情况,我们总结一下: 如果want与acting不相等,且want不等于up,那么会产生pg_temp。
1.2.2 函数start_peering_interval()
上面代码是将pg_temp清除。
2. OSDMonitor端的处理
OSDMonitor接收到MSG_OSD_PGTEMP消息后,按如下方式进行处理:
接下来我们来看对MSG_OSD_PGTEMP
消息的处理:
预处理阶段主要是先进行一些基本的检查:
这里注意到,首先会调用update_up_thru()来建立一个新的up_thru,然后发起一个新的proposal,提交表决,表决通过后将响应返回给OSD。
3. 总结
pg_temp产生的主要原因是:根据osdmap产生的acting set当前不能简单的通过pg log来进行恢复,则此时通过申请pg_temp来暂时担负起这一时期的工作。
[参看]: