-
Notifications
You must be signed in to change notification settings - Fork 861
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BatchPropose会造成状态机恢复时重复Execute或者丢失吗 #56
Comments
我刚刚理解错你的意思了,sorry,我重新回复你一下:phxpaxos的batch propose是多个值绑定在同一个instance里的,其实就是多个client request是成组处理的,多个状态机也是成组执行的,具体请参见SMFac :: BatchExecute(),如果状态机不全部执行完成是不会更新InstanceID的。 我还有个疑问,你为什么要特意提到ExecuteForCheckpoint函数,这个函数是用户自定义的,说Execute函数更合理吧。 |
@niukuo 补充一下:我看到了你提到了5条log,paxos log与instance是一一对应的,所以只有一条log。 |
可能是表述的有问题 里面的“5条log”是想表达5个值的意思 |
上面的场景是说用户应该如何保存Checkpoint |
@niukuo 你说的没错,checkpoint是与上层应用挂钩的,所以phxpaxos很多地方只是提供抽象接口了事。你说的batch propose的ExecuteForCheckpoint其实就是phxpaxos里的SMFac :: BatchExecuteForCheckpoint函数,可以发现,这个函数是执行完所有的客户端请求的状态机之后才返回的,所以不存在你说的多个值执行到一半的情况,肯定是原子的动作。 |
我再具体一点: 一种场景是进程挂掉这种极端情况。 |
@niukuo 我觉得你还是没理解我的意思,batch propose只会调用SMFac :: BatchExecuteForCheckpoint,然后这个函数会一次性调用每个值的SMFac的ExecuteForCheckpoint,不会是每个值单独调用ExecuteForCheckpoint,只有所有ExecuteForCheckpoint执行完毕之后才会更新InstanceID。 具体代码: bool SMFac :: BatchExecuteForCheckpoint(const int iGroupIdx, const uint64_t llInstanceID,
const std::string & sBodyValue)
{
BatchPaxosValues oBatchValues;
bool bSucc = oBatchValues.ParseFromArray(sBodyValue.data(), sBodyValue.size());
if (!bSucc)
{
PLG1Err("ParseFromArray fail, valuesize %zu", sBodyValue.size());
return false;
}
for (int i = 0; i < oBatchValues.values_size(); i++)
{
const PaxosValue & oValue = oBatchValues.values(i);
bool bExecuteSucc = DoExecuteForCheckpoint(iGroupIdx, llInstanceID, oValue.value(), oValue.smid());
if (!bExecuteSucc)
{
return false;
}
}
return true;
} 因为上层应用耦合问题,phxpaxos只是帮用户实现了这个接口,怎么调用还是由用户自己决定,所以在使用phxpaxos库时还是需要对整个流程有个整体的把握才行。 |
CheckpointInstanceID不是用户通过实现GetCheckpointInstanceID返回给phxpaxos的吗 还有代码中
看了一下DoExecuteForCheckpoint里面并没有保存"当前执行到该Instance中第几个值"这个状态,是不是可能存在我上面说的“执行到第3个值时用户return false会导致1,2两个值被重复Execute”。 |
sm.h中没有BatchExecute(ForCheckpoint)接口,所以batch propose最终到达用户的状态机时一定是对同一个instance中的5个值执行多次ExecuteForCheckpoint我的理解是否有问题? |
@niukuo 你理解的没错,假设5个值执行了一半但是挂了,但是并没有什么关系啊,1、2重复执行就重复执行呗,并没有影响数据一致性,因为只要保证instance执行单元是原子的就行,假如你说这么做有问题,那么就算是普通的propose也会有同样的问题,你自己类比一下吧。 |
大部分场景下重复执行可能问题不大 可以先略过 但是上面说的使用ExecuteForCheckpoint生成快照时 是不是可能会漏掉batch propose中的后面几个值呢 执行了第一个值后已经更新了InstanceID 后面几个值没来得及执行时进程挂掉后是不是下次启动会直接从下一个InstanceID开始执行了呢 |
例如进程启动后GetCheckpointInstanceID返回是2 那么下次是会从2开始执行还是3呢 |
@niukuo 所有的值的状态机执行完毕之前不会更新InstanceID,部分执行的值宕机恢复时会重复去执行。具体看代码去吧,不再回复。 |
好的多谢讨论 |
针对单个propose来说,执行状态机和更新instance操作并不是一个事务,也就是说这两者并不是一个原子操作,所以必定导致最后一个instance会重复执行状态机。对于batch也是一样。要解决这个问题,必定是要求paxos和状态机紧密结合,协同设计,而phxpaxos是一个状态机完全开放性的通用库,暂时无法解决这个重复执行问题。但是在大部分场景,状态机自身解决重复执行最后一个instance的问题,还是比较简单的。 |
以下的代码可以重现这个问题
构造了如下场景:
执行结果
instanceID=0的5个值按顺序分别是 e, a, b, c, d |
当你excute返回了false,决不能更新你的checkpoint instanceid,因为下次重启会首先依据你给予的checkpoint instanceid来作为execute的起始点。具体可以参考wiki里面的 checkpoint详解。 |
这里没有影响的。 |
我指的execute返回false是针对整个instance来说的。很明显你应该在整个instance的所有value都execute后,才能更新checkpointid,而第一次的-1变成0已经是错误了。在batch模式下,如何更新chexkpoint是一个要仔细思考的事情。 |
状态机在执行ExecuteForCheckpoint时没有机会知道这是batch中的一个值还是一个单独的instance |
能知道是最后一个固然更好,但目前为了API能向下兼容,暂时不会更改。对于一个有数据的状态机。这里有非常多的简单的办法来生成checkpoint,比如可以执行i的时候生成i-1的checkpoint,这里就不继续讨论了。 |
感谢讨论,希望能够更新一下wiki |
关于batch使用注意事项,确实要更新一些文档。您有兴趣的话也可以写一下,我们会进行采纳:) |
例如状态机InstanceID=1,BatchPropose返回的InstanceID是2。包含5条log。当ExecuteForCheckpoint到中间某一条时进程挂掉,重启时状态机InstanceID是2。会有3条log没有Execute。
此时应该如何保证状态机的一致性?
The text was updated successfully, but these errors were encountered: