三态描述
由于网络异常、机器超载、硬件损坏等等原因,分布式系统中请求结果存在“三态”的概念。
- 在单机系统中,我们调用一个函数实现一个功能,则这个函数要么成功、要么失败,只要不发生宕机其执行的结果是确定的。
- 在分布式系统中,如果某个节点向另一个节点发起 RPC(Remote procedure call)调用,即某个节点 A 向另一个节点 B 发送一个消息,节点 B 根据收到的消息内容完成某些操作,并将操作的结果通过另一个消息返回给节点 A,那么这个 RPC 执行的结果有三种状态:“成功”、“失败”、“超时(未知)”,称之为分布式系统的三态。
三态详解
如果请求 RPC 的节点 A 收到了执行 RPC 的节点 B 返回的消息,并且消息中说明执行成功,则该 RPC 的结果为“成功”。如果请求 RPC 的节点 A 收到了执行 RPC 的节点 B 返回的消息,并且消息中说明执行失败,则该 RPC 的结果为“失败”。但是,如果请求 RPC 的节点 A 在给定的时间内没有收到执行 RPC 的节点 B 返回的消息,则认为该操作“超时”。对于超时的请求,我们无法获知该
请求是否被节点 B 成功执行了。这是因为,如果超时是由于节点 A 发向节点 B 的请求消息丢失造成的,则该操作肯定没有被节点 B 成功执行;但如果节点 A 成功的向节点 B 发送了请求消息,且节点 B 也成功的执行了该请求,但节点 B 发向节点 A 的结果消息被网络丢失了或者节点 B 在执行完该操作后立刻宕机没有能够发出结果消息,从而造成从节点A看来请求超时。所以一旦发生超时,请求方是无法获知 RPC 的执行结果的。 如下:
一个非常易于理解的例子是在网上银行进行转账操作,当系统超时,页面提示:“如果系统长时间未返回,请检查账户余额以确认交易是否成功”。
分布式系统一般需要区别对待 RPC 的“成功”、“失败”、“超时”三种状态。 当出现“超时”时可以通过发起读取数据的操作以验证 RPC 是否成功(例如银行系统的做法)。另一种简单的做法是,设计分式协议时将执行步骤设计为可重试的,即具有所谓的“幂等性”。例如覆盖写就是一种常见的幂等性操作,因为重复的覆盖写最终的结果都相等。如果使用可重试的设计,当出现“失败”和“超时”时,一律重试操作直到“成功”。这样,即使超时的操作实际上已经成功了,重试操作也不会对正确性造成影响,从而简化了设计。