消息队列的消息异常处理
目录
1.如果消费端发生异常导致消息消费失败,补偿策略是什么
2.消息队列重试的话,如何保证消费的幂等性?
3.消息重发机制
1.如果消费端发生异常导致消息消费失败,补偿策略是什么
生产者发送消息失败:
设置mandatory=true;交换器无法根据自身的类型和路由键找到一个符合条件的队列的话,那么RabbitMQ会调用Basic.Return命令将消息返回给生产者
生产者将信道设置成confirm(确认)模式:一旦信道进入confirm模式,所有在该信道上面发布的消息都会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后,RabbitMQ就会发送一个确认(Basic.Ack)给生产者(包含消息的唯一ID)
消费者消费消息失败:
设置死信队列:消息进入死信队列,设置重新发送到正常队列的重试时间和重试间隔,重新发送到正常队列
将消息存入本地客户端:进行重发
补偿策略:当消息消费失败后,进入死信队列,获取对应死信队列的消息长度,当大于0时并判断未超过重试次数,自动将消息从死信队列迁移到正常队列
死信队列:如果队列里的消息出现存活时间超过设置的生存时间(TTL)时间、消息数量已经超过最大队列长度,该消息将成为“死信”。
“死信”消息会被RabbitMQ进行特殊处理,如果配置了死信队列信息,那么该消息将会被丢进死信队列中,如果没有配置,则该消息将会被丢弃。
2.消息队列重试的话,如何保证消费的幂等性?
消费的幂等性:消费者对某条消息重复消费的情况时,重复消费的结果与消费一次的结果是相同的,并且多次消费并未对业务系统产生任何负面影响
利用数据库的唯一约束实现幂等:比如将订单表中的订单编号设置为唯一索引,创建订单时,根据订单编号就可以保证幂等
利用redis的原子性:每次操作都直接set到redis里面,然后将redis数据定时同步到数据库中
版本号机制:给业务数据增加一个版本号属性,每次更新数据前,比较当前数据的版本号是否和消息中的版本一致,如果不一致则拒绝更新数据,更新数据的同时将版本号+1
3.消息重发机制
消息重发:消息发送失败或者消费者消费失败后重新发送消息
在消息收发过程中,若Consumer消费某条消息失败或者消费超时,则云消息队列会在重试间隔时间后,将消息重新投递给消费者消费,若达到最大重试次数后消息还未被成功消费,则将消息投递至死信队列,通过私信消息解决业务异常
消息重试行为:
重试间隔:上一次消费失败或超时后,距下次消息可被重新消费的间隔时间
最大重试次数:消息消费失败后,可以被消息队列重复投递的最大次数