##up_thru
up_thru的概念的引入,是为了解决当断电,或者其它原因,同时导致两个以上的osd处于down,但是monitor在两次epoch 中检测到了这种状态, 从而导致monitor认为它们是先后down掉,后down 的osd 有可能产生数据的更新,这导致需要等待该osd的恢复,否则有可能产生数据丢失。
下面举例说明:
epoch | 处于 up 的 osd |
---|---|
1 | A B |
2 | B |
3 | |
4 | A |
如上所示的过程:
- 在epoch为1时,一个pg中有A,B两个osd(两副本),都处于up的状态
- 在epoch 为2时,monitor 只检测到了A 处于down,B 仍然处于 up状态:
-
情况1:此时如果B确实处于up状态,由于B上保持了完整的数据,pg可以完成peering过程,pg就可以处于active的状态,可以接受数据写操作。
-
情况2:如果B其实也已经和A同时down,只是monitor没有检测到。此时pg不可能完成pg的peering过程,pg可写。
上述两种不同的情况,monitor无法区分。
- 在epoch为3时,Monitor检测到B 也down了。
- 在epoch为4时,A恢复了up的状态,此时该PG 在peering完成后,是否可以处于active状态,继续接受读写操作?
- 如果在epoch为2 时,属于情况2,pg并没有数据更新,B上不会有新的数据,A不缺失数据,此时pg可以处于active状态,可以接受更新请求;
- 如果属于情况1,pg上有新数据更新到了osdB, 此时osd A 缺失一些数据,该pg 不会处于active 状态。
为了使monitor能够区分上述两种情况,引入了up_thru的概念,up_thru记录了每个osd完成peering后的epoch值。
如果是上述情况2, pg如果可以恢复为active状态,在peering完成后,必须先向Monitor发送消息,Monitor用数组up_thru[osd] 来记录该osd处于active时的epoch值。
当引入up_thru后,上述例子的处理如下:
情况1:
epoch | 处于 up 的 osd | monitor up_thru |
---|---|---|
1 | A B | up_thru[B]=0 |
2 | B | up_thru[B]=0 |
3 | ||
4 | A |
流程如下:
- 在epoch1时,up_thru[B]为0,也就是说B在epoch为0时参与完成peering。
- 在epoch2时,Monitor检查到osd A 处于down状态,osd B 还处于up状态,osd B没有peering成功,没有向monitor 上报其新的up_thru值,该up_thru没有更新。
- epoch3时,AB都down了。
- epoch4时,A节点处于up状态,开始Peering,发现up_thru[B]为0,说明在epoch 2是没有更新操作,该pg可以完成peering,处于activate状态。
epoch | 处于 up 的 osd | monitor up_thru |
---|---|---|
1 | A B | up_thru[B]=0 |
2 | B | up_thru[B]=0 |
3 | up_thru[B]=2 | |
4 | ||
5 | A |
情况2:
流程如下:
- 在epoch1时,up_thru[B]为0,也就是说B在epoch为0时参与完成peering。
- 在epoch2时,Monitor检查到osd A 处于down状态,osd B 还处于up状态,该pg 完成了peering,向monitor 上报B的up_thru变为当前epoch2,有可能有更新操作。
- epoch3时,AB都down了,B的up_thru为2。
- epoch5时,A节点处于up状态,开始Peering过程,发现up_thru[B]为2,说明在epoch 为2时完成了peering,有可能有更新操作,该pg需要等待B恢复,否则可能B上更新的数据,从而产生数据丢失的风险。。