Ceph H版本monitor Paxos相关流程分析




问题1:哪些变更需要通过Paxos进行决议?

初始化流程:

可以根据初始化流程看出上述所有dispatch函数都是基类的PaxosService::dispatch。

问题2:决议间隔时间的用途是什么?该间隔内产生的多个提案是批量提交给Paxos服务进行决议的吗?

决议间隔时间由配置项paxos_propose_interval确定,默认值是1s,paxos_min_wait是最小间隔时间,默认0.05s。
两个配置项的用途:

我理解之所以有这2个间隔,主要是为了防止决议过程阻塞dispatch线程,尤其是paxos_min_wait这个只有0.05s,实际上这么短时间的定时器是没有意义的,主要是为了切换到timer线程。

在决议间隔时间段内,所有的待决议提案都是保存在内存中的,等待delay时间到了才进行决议:

用pgmap举例(osdmap是OSDMonitor::prepare_update):

prepare_update之后就是PaxosService::propose_pending,

问题3:Paxos决议流程是什么样的?有几个线程处理提案(或者说有几个Paxos服务线程)?

首先看线程问题,根据代码可以看出,Paxos接收更新并分发给各个service只是dispatch线程在处理,但实际上由于timer线程、finisher线程(各一个)的介入,所以可以认为是2个线程在处理,dispatch只负责预处理value更新消息,之后由timer线程进行提案处理,或者由finisher线程完成回调,决议过程由多个monitor共同完成(单monitor除外)。

多个service(pg、osd等)之间是使用相同的线程,但定时器和finisher线程是一个,

其次看下Paxos决议流程(https://www.jianshu.com/p/7302e79ab534 这篇文档写的比较清晰,尤其是流程图):

  1. Leader将提案追加在本地Log(pending_inc),并向Quorum中的所有节点发送begin消息,消息中携带提案值、Pn及指向前一条提案version的last_commit;如果只有一个monitor节点(Quorum=1),则跳过begin、accept阶段直接commit
  2. Peon收到begin消息,如果accept过更高的pn则忽略,否则提案写入本地Log并返回accept消息。同时Peon会将当前的lease过期掉,在下一次收到lease前不再提供服务;
  3. Leader收到全部Quorum的accept后进行commit。将Log项在本地DB执行,返回调用方并向所有Quorum节点发送commit消息;
  4. Peon收到commit消息同样在本地DB执行,完成commit;
  5. Leader追加lease消息将整个集群带入到active状态。

步骤1代码:

步骤2代码:

步骤3代码(不考虑超时情况,超时则走选主流程):

步骤4代码:

步骤5代码:

问题4:osdmap、pgmap、monmap是一起决议的吗?

各自决议或者说各自提交提案,但是决议流程完全相同,对Paxos服务来说没有差别(只是提案携带的value等参数不同)。

这就表示他们相互之间是串行的(相对dispatch线程和leveldb落盘操作来说是串行,相对Paxos服务并不完全是,参考上面提到的timer线程和finisher线程),可能会互相影响。

问题5:决议结果是怎么落盘的?一次决议会落盘几次?

根据上面的问题3代码分析,可以看出一次决议有4次落盘(从角色看leader、peon各两次,具体到决议过程是begin阶段leader、peon各一次,commit阶段leader、peon各一次),其中leader在收到peon的accept回复之后的commit阶段的落盘是异步的,其他都是同步。

但是不管同步还是异步落盘,对提案提交者来说,总是要等待决议通过之后才能收到回复,才能继续执行后续流程。

同步落盘:

异步落盘:

问题6:为啥集群没有IO也会进行决议?

pgmap、logm及少量的auth,其中pgmap是在osd在上报pg stats,即使pg stats没有变化,也要120s(osd_mon_report_interval_max)上报一次:
OSD::tick -> OSD::do_mon_report -> OSD::send_pg_stats

问题7:leveldb定期清理怎么做?

之后的流程跟正常的决议流程一致,只是leveldb操作变为erase(正常都是put)。

问题8:有哪些手段可以分析Paxos耗时问题?

H版本:
只有少量perf dump数据,包括Paxos和leveldb驱动相关的,

新版本:
1. 新版本mon增加了op tracker功能,类似osd的tracker,只能查看ops,看起来还没有增加类似osd的dump_historic_ops相关功能(src\mon\MonOpRequest.h:mark_paxos_event、mark_pgmon_event等)
2. rocksdb驱动增加了一些perf统计信息,可以参考加到leveldb驱动中。

日志补充方案

  1. 参考新版本rocksdb补充leveldb相关perf计数器数据
  2. 增加单次leveldb落盘操作阈值配置项,超出阈值的操作打印日志
  3. 增加osd alive、boot重点消息的回复日志(根据接收到消息的时间戳计算monitor服务耗时,耗时超过预设阈值的消息才打印)
  4. Paxos决议流程增加多个monitor之间交互的日志(耗时超过一定阈值的才打印)

线上waitupthru耗时20多秒问题分析

针对线上环境waitupthru耗时长达20+s的问题,根据代码流程分析,有两个怀疑的点:
1. leveldb落盘较慢,串行操作场景多次决议加落盘导致后面的提案阻塞 — 可能性低,因为已经更换ssd盘,并且根据perf dump统计5s内Paxos平均commit耗时并不长(100+ms),commit次数也不高(10次左右)
2. 多个monitor之间交互耗时较长,leader等待peon accept后才能commit — 可能性相对较高,怀疑是受dispatch线程影响(pg、osd、log等需要决议的提案或者执行的命令数量太多,来不及处理?)
3. 上述两种情况叠加导致

当前可以优化的监控项

  1. 在之前的mon Paxos perf监控基础上补充更多监控项,例如begin阶段、store阶段等的耗时,dispatch线程throttle情况、leveldb相关数据等