pg Incomplete和inconsistent状态源码逻辑和解决

时间:2024-05-21 08:51:20

            首先我们从字面意思理解下这2个pg状态。

             Incomplete : 没完成

             inconsistent : 不一致

             那么是什么没完成和不一致呢? 简单来说Incomplete是pg peering没完成。inconsistent 是pg三副本中的数据不一致


一, Incomplete解说


                     pg Incomplete的实验方式:设置min_size足够大并且
osd_allow_recovery_below_min_size为false。 当设置好上述两个条件以后,那么需要将集群变为peering状态,这时只需要手动将一个osd down掉即可,然后ceph -s 发现集群有imcomplete状态了

                     pg Incomplete状态常见于ceph集群在peering状态下,来回重启服务器,或者掉电。peering本来是ceph一个全自动化的过程,为什么会造成没有完成?任何程序都会走到未知的异常流程里,也就是说这个异常是不符合逻辑的,根据逻辑是不会产生的,但他确实产生了,下面我们来看看Incomplete状态在什么时候抛出。

                    1,Incomplete状态在peering-->getLog状态中出现,也就是说,在选择权威日志的时候,权威日志没法完成,或者权威日志完成后和本地日志对比逻辑不正常,此时抛出Incomplete状态

                      pg Incomplete和inconsistent状态源码逻辑和解决

                     getLog里有2处地方抛出Incomplete。第1处地方是选择权威日志,如果选择权威日志失败,并且want_acting为空,那么就Incomplete。 第2处,如果权威日志选择成功,但是本地日志最后一次更新小于权威日志的日志尾,那就说明本地日志和权威日志不能重叠,那就有矛盾了,既然权威日志能选出来,那肯定日志重叠的,所以抛出Incomplete。

                     我们再看第1处,为什么权威日志不能选出来?原因如下(暂时不考虑EC):

pg Incomplete和inconsistent状态源码逻辑和解决

              Getlog()调用choose_acting()来选择权威日志,choose_acting()调用find_best_info()选择权威日志,如果find_best_info()选择权威日志失败,那么创建临时pg,要么保持want_acting为空。 而这2个条件必然导致Getlog()里触发Incomplete。

    我们再看find_best_info()为什么会没有选出权威日志

pg Incomplete和inconsistent状态源码逻辑和解决

                      首先给min_last_update_acceptable的成员初始化一个unsigned int最大值eversion_t::max(),

pg Incomplete和inconsistent状态源码逻辑和解决

                  因为max的成员都是unsigned int型,所以-1,就是unsigned int最大值。然后看>操作符

pg Incomplete和inconsistent状态源码逻辑和解决

                    如果min_last_update_acceptable > i->second.last_update,那就赋值为i->second.last_update。否则不赋值

             如果在不赋值的情况下,权威日志就选择失败,返回infos.end()。但是min_last_update_acceptable是一个unsigned int最大值,可能会比 i->second.last_update小吗? 所以这又是一个不符合逻辑的地方,要抛出Incomplete状态。

                下面我们再看一个不符合逻辑的地方:

pg Incomplete和inconsistent状态源码逻辑和解决

              假如找不到足够可以恢复日志的acting set,那么want_acting设置为空,并返回false,也就是抛出Incomplete。

getinfo(),和find_best_info()选择权威日志的逻辑都走完了,这时候说没有足够的acting osd来恢复日志,这不是打脸吗?


             总结:Incomplete都是源于在日志peering,或者说选择权威日志的时候出现了意想不到的错误导致的,大部分因为在peering的时候,掉电,反复重启osd所致,所以ceph要提醒用户,因为日志的异常,不能合并,所以需要用户手动操作来恢复pg状态,首先要拿出pg三副本中的数据对比,人工选出一份可靠的pg,一般选择数据比较全的那个pg副本,使用ceph-objectstore-tool把自己提取出的权威pg,导入其他2个副本pg,强行使其一致。


二,inconsistent详解


                pg inconsistent 根源是pg的三副本数据不一致,三副本中,其中2个副本是"aaaa",另外一个副本是"bbbb",那么三副本中的数据就不一致。一般是ceph scrub的时候发现的,ceph scrub扫描磁盘上三副本数据不一致的情况,磁盘上可能发生数据位反转。一般情况是用ceph pg repair pgid 可以自动修复

                下面我们做几个实验

                 1,用ceph pg dump,找一个实验pg,然后修改其他一个副本,修改后,使用ceph pg scrub pgid 查找这个pg的不一致,扫描后,ceph -s,ceph集群会报inconsistent异常,使用ceph health detail可以查看是哪个pg异常。然后用ceph pg repair pgid 修复,发现可以修复。

                 2,按照上面方法,修改三个副本,改成不一致。发现ceph pg repair pgid修复后,没有用。

                 3,按照上面方法,修改三个副本,其中一个副本修改原来的数据aaaa,修改后,还是改成aaaa,虽然修改了,但是依然保持数据不变。 另外2个副本随意修改。发现ceph pg repair pgid修复后,居然没有用。

                 综合上面三次实验,为什么第三次实验明明有一份正常的数据,但是不能修复呢? ceph怎么找出一个权威的对象来修复数据呢?根据哪个对象副本来修复?

                  根据实验2和3发现,ceph根本不是任意选择一个副本数据,来修复其他2个副本的数据,而是要根据ceph自己的原则来选择一个权威对象来修复,在 be_select_auth_object()函数里面,根据object_info_t中 ( 对象的size, omap的digest,data的digest ) 与ceph pg repair pgid扫描出的对象数据,进行比对。确定一个一直没有被改动过的对象,就是权威对象。

pg Incomplete和inconsistent状态源码逻辑和解决

                 总结:当三副本不能选出权威日志时候,说明三个副本的对象都被动了,这时候我们要手动选出一个权威对象,核对自己的业务数据,或者选择一个最大的对象,做到止损。选择了权威对象后,用ceph-objectstore-tool导出对象的pg,导入其他2个副本。