消息投递保证
一.消息投递保证分类
消息的投递保证主要是三种形式:
1.At most once—Messages may be lost but are never redelivered.
最多一次 --- 消息可能丢失,但绝不会重发。
2.At least once—Messages are never lost but may be redelivered.
至少一次 --- 消息绝不会丢失,但有可能重新发送。
3.Exactly once—this is what people actually want, each message is delivered once and only once.
正好一次 --- 这是人们真正想要的,每个消息传递一次且仅一次。
这三种消息投递保证包含两方面的内容:生产者发送消息和消费者消费消息。
二.生产者消息投递保证分类
1.最多一次
客户端只发送一次,不关心发送成功与否
2.至少一次
通常会设置一个最大重试次数,在发送失败且未达到重试次数前,会多次重试。
当消息中间件保存消息成功但向客户端响应失败的情况下,生产者会将同一条消息发送多次,导致消息重复。
3.正好一次
1)需要生产者能够根据消息中的内容生产一个唯一且不重复的ID,如果ID相同则认为消息体相同
2)如果消息中间件支持根据某一个属性进行幂等操作,则直接利用该特性实现“正好一次”。即使消息中间件具备该功能,也是有时间限制的,在使用时需要具体了解
3)如果消息中间件不支持该特性,则无法实现该中投递保证。因为对于消息中间件保存消息成功但向客户端响应失败的情况在生产者一端是没有办法解决的
三.消费者消息投递保证分类
1.最多一次
先更新消费的offset,而后进行消息消费,这样消息处理过程中崩溃了(进程或者机器),也不会再次进行消费。
2.至少一次
先处理消息,处理完成后再更新消费的offset。这样当消息处理过程中崩溃了(进程或者机器),当恢复后会再次消费消息。
3.正好一次
通常需要在消费者位置的存储和消费者输出的存储之间引入分布式事务来实现,只有当消息处理成功后再更新消息的offset,通过这种方式来保证“正好一次”。 一个简单的方法是把记录消息消费的offset和消息处理结果使用同一条sql保存在一张表中。
也可以采用“二级消费"的方式来实现”正好一次“,自己搭建一个系统和db来存储消息ID,对重复的消息ID进行过滤,来保证重复的消息只有一条(http://blog.jobbole.com/111809/?utmsource=blog.jobbole.com&utmmedium=relatedPosts)。
四.通常选择
对于大多数系统而言,是不会接受消息丢失,而正好一次的实现成本又比较高,因而在消息中间件实际的运用中,使用最广泛的是“至少一次”这种投递保证,也是消息中间件的默认选项。
五.参考资料
1.http://orchome.com/21