Producer在把Message发送Broker的过程中,因为网络问题等发生丢失,或者Message到了Broker,但是出了问题,没有保存下来。针对这个问题,Producer可以开启MQ的事务,如果这个过程出现异常,进行回滚,但是有个很大的问题,你提交一个事务就会阻塞在那,非常影响性能,生产环境肯定不会开启事务,一般都是使用confirm机制
Broker接收到Message暂存到内存,Consumer还没来得及消费,Broker挂掉了
可以通过持久化设置去解决:
1.创建Queue的时候设置持久化,保证Broker持久化Queue的元数据,但是不会持久化Queue里面的消息
2.将Message的deliveryMode设置为2,可以将消息持久化到磁盘,这样只有Message支持化到磁盘之后才会发送通知Producer ack
这两步过后,即使Broker挂了,Producer肯定收不到ack的,就可以进行重发
Consumer有消费到Message,但是内部出现问题,Message还没处理,Broker以为Consumer处理完了,只会把后续的消息发送
这时候,就要关闭autoack,消息处理过后,进行手动ack
整体流程:
整体流程:
相比第一种方案,这里减少了一次message入库,confirm机制是消息可靠性投递的一个核心,在下篇文章会讲到
首先,无论是RabbitMQ、RocketMQ还是kafka,都有可能出现消息的重复发送,这个是MQ无法保障的,而幂等性是开发或者运维人员需要保证的
所谓消息的幂等性是指即使收到多次消息,也不会重复消费,这点很重要,例如用户付钱,点的太快了,付了多次,但是你也只能扣一次钱
在Consumer端offset没有提交的时候,Consumer重启了,这时候就会出现重复消费的情况
整体实现相对简单,需要进行数据库写入,利用数据库主键去重,使用ID进行分库分表算法路由,从单库的幂等性到多库的幂等性
Redis的实现性能比较好,而且Redis一般使用集群,不用担心某台机器挂掉了,影响服务。
存在的问题:是否要进行数据落库,如果落库的话,怎么保证缓存和storage的一致性、事务,如果不落库,如何设置定时同步
原文:https://www.cnblogs.com/scholar-hwg/p/12071833.html