如何处理裂脑?

How to handle split-brain?

我在 Orleans 常见问题解答中读到了什么时候可能会发生裂脑,但我不明白会发生什么坏事以及如何正确处理它。

常见问题解答含糊不清,例如:

You just need to consider the rare possibility of having two instances of an actor while writing your application.

但实际上我应该如何考虑这一点,如果我不考虑会发生什么?

奥尔良纸业 (http://research.microsoft.com/pubs/210931/Orleans-MSR-TR-2014-41.pdf) 是这样说的:

application can rely on external persistent storage to provide stronger data consistency

但是我不明白这是什么意思。

假设发生了脑裂。现在我有两种情况的一种谷物。当我发送几条消息时,它们可能会被这两个(或者可能有更多?)不同的实例接收到。假设每个实例在收到这些消息之前都具有相同的状态。现在,在处理这些消息后,它们具有不同的状态。

他们应该如何坚持他们的状态?可能有冲突。

当另一个实例将被销毁而只剩下一个实例时,被销毁实例的状态会发生什么变化?就像他们处理过的消息从未被处理过一样?然后客户端状态和服务器状态可以去同步IIUC。

我认为这(裂脑)是一个大问题,我不明白为什么人们对它的关注如此之少。

Orleans 利用存储提供商的一致性保证。当你从 grain 调用 this.WriteStateAsync() 时,存储提供者确保 grain 已经看到所有以前的写入。如果没有,则抛出异常。您可以捕获该异常并调用 DeactivateOnIdle() 并重新抛出异常或调用 ReadStateAsync() 并重试。因此,如果在裂脑情况下你有 2 个谷物,哪个先调用 WriteStateAsync() 会阻止另一个在没有先读取最新状态的情况下写入状态。

更新:从 Orleans v1.5.0 开始,当当前执行的调用完成时,允许将 InconsistentStateException 返回给调用者的 grain 将自动停用。 grain 可以catch 并处理异常以避免自动停用。