在消息传递过程中,如果出现传递失败的情况,发送方会执行重试,重试过程中就有可能产生重复的消息。如果没有对重复消息进行处理,就可能导致系统的数据出现错误。
比如,一个消费订单消息,统计下单金额的微服务,如果没有正确处理重复消息,那就会出现重复统计,导致统计结果错误。
一、消息重复的情况必然存在
在MQTT协议中,给出了三种传递消息时能够提供的服务质量标准:
这个服务质量标准不仅适用于 MQTT,对所有的消息队列都是适用的。常用的绝大部分消息队列提供的服务质量都是 At least once,包括 RocketMQ、RabbitMQ 和 Kafka 。也就是说,消息队列很难保证消息不重复。
注意:Kafka 支持的“Exactly once”和我们刚刚提到的消息传递的服务质量标准“Exactly once”是不一样的,它是 Kafka 提供的另外一个特性,Kafka 中支持的事务也和我们通常意义理解的事务有一定的差异。在 Kafka 中,事务和 Excactly once 主要是为了配合流计算使用的特性。
二、用幂等性解决重复消息问题
幂等本来是一个数学上的概念,它的定义是:如果一个函数f(x)满足:f(f(x)) = f(x),则函数f(x)满足米幂等性。扩展到计算机领域,被用来描述一个操作、方法或者服务。
例子:
1、在不考虑并发的情况下,“将账户 X 的余额设置为 100 元”,执行一次后对系统的影响是,账户 X 的余额变成了 100 元。只要提供的参数 100 元不变,那即使再执行多少次,账户 X 的余额始终都是 100 元,不会变化,这个操作就是一个幂等的操作。
2、“将账户 X 的余额加 100 元”,这个操作它就不是幂等的,每执行一次,账户余额就会增加 100 元,执行多次和执行一次对系统的影响(也就是账户的余额)是不一样的。
总结:
原文:https://www.cnblogs.com/chjxbt/p/11428786.html