我有一个这样的系统:
可能出现问题的情况包括:
其他一些节点也可能会并行读取该事件的副本,因此现在会发送2封电子邮件。
节点1读取事件,发送电子邮件'在没有确认发送的电子邮件的情况下打电话然后死节点1不知道电子邮件是否已发送,因此在重新启动后会重新发送。
我如何确保只发送一次电子邮件?
答案 0 :(得分:1)
我认为情景1通常由大多数现代排队系统处理。我认为还有其他问题可以更好地解决锁定问题,所以我暂时忽略它。
关于方案2,大多数现代排队系统都处理同样的问题 - 它基本上归结为一个关于你想如何失败的问题。
例如,如果您必须选择两次发送电子邮件或不发送电子邮件,您会选择哪种?在队列用语中,这被描述为至少一次与最多一次交付。
对于这些答案,我假设像RabbitMQ这样的排队系统可以实现确认和超时。
选项1 - 两次发送电子邮件 尝试发送电子邮件,如果成功,则将消息发送到队列。设置队列,以便在超时后重新添加未确认的消息。在这种情况下,如果在发送过程中发生故障,则不会发生确认,并且该消息将重新发送到队列,然后再次拾取。现在,如果ack(但不是您的电子邮件)一直出现故障,您最终可能会继续发送电子邮件。然而,在大多数情况下,这不应该是一个问题。
选项2 - 不提供电子邮件 设置一个没有确认的队列。这通常更高效,所以这是一个优点。队列工作人员将从队列中接收消息并尝试发送电子邮件。如果电子邮件无法发送,则不会重试。
对于我工作的许多服务(这不适用于电子邮件,但确实适用于写入数据库),我尝试使它们具有幂等性,然后只使用第一个选项。在最糟糕的情况下,你会改变写入,但希望你有记录来检测它。