Ceph源码解析:PG peering(4)

    // See doc/dev/osd_internals/last_epoch_started
    if (oinfo.last_epoch_started > info.last_epoch_started)
    {
        info.last_epoch_started = oinfo.last_epoch_started;
        dirty_info = true;
    }
    if (info.history.merge(oinfo.history))  //对history信息进行合并。
        dirty_info = true;
    assert(cct->_conf->osd_find_best_info_ignore_history_les ||
          info.last_epoch_started >= info.history.last_epoch_started);

    peer_missing[from].swap(omissing);//将missing结构统计到本地的peer_missing结构中。
}

auth_log:一个是auth_log的合并,最大最权威的log,恢复数据要根据这里进行。

missing:另外就是合并log过程中发现本地副本需要恢复的object集合。

omissing:auth_osd需要进行恢复的object集合。

3、GetMissing:

3.1、遍历acting_backfill,向与primary pg log有交集的pg所在的osd发送Query Log请求;将剩余没有交集的pg放入peer_missing,生成missing set用于后续recovery;

context< RecoveryMachine >().send_query(
                *i,
                pg_query_t(
                    pg_query_t::LOG,
                    i->shard, pg->pg_whoami.shard,
                    since, pg->info.history,
                    pg->get_osdmap()->get_epoch()));

3.2、将收到的每一个应答merge到本地,如果在此期间有osd down掉,这个PG的状态将持续等待;收到所有的应答后,当前pg的状态机进入Activate状态,peering过程结束;

boost::statechart::result PG::RecoveryState::GetMissing::react(const MLogRec &logevt)

{
    PG *pg = context< RecoveryMachine >().pg;

    peer_missing_requested.erase(logevt.from);
   
pg->proc_replica_log(*context<RecoveryMachine>().get_cur_transaction(),
                        logevt.msg->info, logevt.msg->log, logevt.msg->missing, logevt.from);//接收到其他osd发回的log信息并且进行处理。在proc_replica_log中对peer_log进行修剪,丢弃那些不完整不可用的log。整理接收到的oinfo到peerinfo中,omissing到peer_missing中。直接来到active状态。

    if (peer_missing_requested.empty())
    {
        if (pg->need_up_thru)
        {
            dout(10) << " still need up_thru update before going active" << dendl;
            post_event(NeedUpThru());
        }
        else
        {
            dout(10) << "Got last missing, don't need missing "
                    << "posting Activate" << dendl;
           
post_event(Activate(pg->get_osdmap()->get_epoch()));
        }
    }
    return discard_event();
}

3、总结

从以上分析来看,整个peering过程主要分为三个阶段,GetInfo -> GetLog -> GetMissing,首先向prior set、acting set、up set中的每个osd请求pg infos, 选出authoritative log对应的pg;其次向authoritative log所在的osd请求authoritative log;最后获取recovery过程需要的missing set;

peering时间的长短并不可控,主要是在于请求的osd是否能够及时响应;如果这个阶段某个osd down掉,很可能导致部分pg一直处在peering状态,即所有分布到这个pg上的IO都会阻塞。

此文仅讲述了peering过程,peering之后还会进行recovery操作,recovery操作由处理线程直接调用函数void OSD::do_recovery(PG *pg, ThreadPool::TPHandle &handle)进行,后续再总结总结recovery过程和PG的状态机。

先附两张PG状态机的类型以及流程图:

Ceph源码解析:PG peering

Ceph源码解析:PG peering

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

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