可靠交付允许出现重复
消息系统若在没有取得可靠确认时重新发送,就可能把同一消息再次交给消费者。至少一次语义把这种重复纳入契约,使用者不能仅因一项工作曾经被领取,就假定系统不会再次交付。
Amazon SQS标准队列保存多份副本;某个副本所在服务器在接收或删除时不可用,之后可能再次给出那份消息。AWS据此要求应用能够承受重复处理,而不把一次删除响应理解为所有副本从此绝不再出现。
参考:[1]
确认覆盖哪一段交接
发布端获得消息代理的确认,与代理获得消费者处理确认,是不同链路。RabbitMQ明确说明发布确认不了解消费者状态,消费者确认也不是发给原发布者的业务响应。
在RabbitMQ手动确认模式下,通道或连接关闭时,尚未确认的消息会重新入队。这有助于故障恢复,却也使消费者可能收到之前交给其他消费者的内容;处理责任不能只用当前连接是否还存在判断。
参考:[2]
投递次数与业务效果分开处理
如果业务修改已完成,确认却在故障中丢失,再次投递不应无条件再次扣款或追加同一记录。幂等操作、稳定请求身份与一致保存处理结果,可以把重复交付约束在约定效果内。
至少一次也不是对任何故障、任意保留期限或无限停机的无条件承诺;需要按服务的存储、确认和恢复契约理解。判断系统是否可靠,应沿发布、代理持有、消费者执行与最终效果逐段核对,而不只统计消息收到了几次。