长版:
我是erlang的新手,并考虑将其用于可扩展的架构。我发现该平台的许多支持者都在宣传其可靠性和容错性。
但是,我很难准确理解在这个消息在瞬态内存中排队的系统中如何实现容错。我知道可以安排一个主管层级来重新生成已故的流程,但我一直无法找到很多关于重生工作对正在进行的工作的影响的讨论。在飞行中的消息和在垂死节点上丢失的部分完成的工作的工件会发生什么?
当消费者进程死亡时,所有生成器是否会自动重新传输未获取的消息?如果没有,这怎么可以被认为是容错的?如果是这样的话,是什么阻止了被处理的消息 - 但是没有完全确认 - 被重新传输,因此被不适当地重新处理?
(我认识到这些问题不是erlang独有的;任何分布式处理系统都会出现类似的问题。但是erlang爱好者似乎声称平台让这一切变得“容易”......?)
假设重新传输消息,我可以很容易地设想一个场景,在发生故障后,复杂消息链的下游影响可能变得非常混乱。如果没有某种繁重的分布式事务系统,我不明白如何在不解决每个进程中的重复的情况下保持一致性和正确性。我的应用程序代码是否必须始终强制执行约束以防止事务被多次执行?
简短版:
分布式erlang进程是否受重复消息的影响?如果是这样,是重复保护(即,幂等)应用程序的责任,还是erlang / OTP以某种方式帮助我们?
答案 0 :(得分:107)
答案 1 :(得分:4)
erlang OTP系统具有容错能力。这并不能减轻您在其中构建同样容错的应用程序的需要。如果你使用erlang和OTP,那么你可以依赖一些东西。
据我所知,erlang中的消息不会重复。如果您发送消息并且进程收到消息,则消息将从队列中消失。但是,如果您发送消息并且进程收到该消息但在处理它时崩溃,则该消息将消失并且未处理。在您的系统设计中应该考虑这个事实。 OTP通过使用进程从可能发生崩溃的应用程序代码中隔离基础架构关键代码(例如,supervisor,gen_servers,...)来帮助您处理所有这些。
例如,您可能有一个gen_server将工作分派给进程池。池中的进程可能会崩溃并重新启动。但gen_server仍然存在,因为它的全部目的只是接收消息并将它们发送到池中进行处理。这样,即使游泳池中出现错误和崩溃,整个系统也能保持正常运行,并且始终有一些东西在等待您的消息。
仅仅因为系统是容错的并不意味着你的算法是。
答案 2 :(得分:1)
我认为答案根本与Erlang无关。它位于客户端 - 服务器交互的语义中,您可以选择在客户端 - 服务器协议中实现“至少一次”,“最多一次”或“完全一次”保证。 所有这些调用语义都可以通过在发送或执行客户端和服务器之前组合唯一标记,重试和记录客户端请求来实现,以便在崩溃后服务器可以拾取它。 除了重复之外,您还可能收到丢失,孤立或延迟的消息。