说到消息消费不得不提消息的幂等性,业务代码中通常收到一条消息进行一次业务逻辑处理,如果一条相同消息被重复收到几次,是否会导致业务重复处理?Consumer能否不重复接收消息?
RocketMQ不保证消息不被重复消费,如果业务对消费重复非常敏感,必须要在业务层面进行幂等性处理,具体实现可以通过分布式锁来完成。
在所有消息系统中消费消息有三种模式:at-most-once(最多一次)、at-least-once(最少一次)和exactly-only-once(精确仅一次),分布式消息系统都是在三者取平衡,前两者是可行的并且被广泛使用的。
-
at-most-once:消息投递后不论消费是否成功,不会再重复投递,有可能会导致消息未被消费,RocketMQ未使用该方式。
-
at-least-once:消息投递后,消费完成后,向服务器返回ACK(消息确认机制),没有消费则一定不会返回ACK消息。由于网络异常、客户端重启等原因,服务器未能收到客户端返回的ACK,服务器则会再次投递,这就会导致可能重复消费,RocketMQ通过ACK来确保消息至少被消费一次。
-
exactly-only-once:必须下面两个条件都满足,才能认为消息是exactly-only-once。1.发布消息阶段,不允许发送重复的消息; 2.消费消息阶段,不允许消费重复的消息。在分布式系统环境下,如果要实现该模式,巨大的开销不可避免。RocketMQ为了追求高性能,并不保证此特性,无法避免消息重复,由业务上进行幂等性处理。
以下是看黑马-RocketMQ系统精讲讲到的消息幂等概念: