防止消息重复消费:
在本地数据库或Redis做业务标识,比如用户ID或者订单ID,每次消费前先校验,保障接口幂等性
消息丢失解决:
- 生产者—中间件:只需要做好ACK、异常处理进行消息重发,可以保证不丢消息
- 中间件存储:部署MQ集群,即使一个节点丢了也有副本
- 消息者处理阶段:必须消费完成才能ACK,否则消费中途挂掉了会导致消息丢失
消息可靠性:
- 消息持久化:开启MQ的消息持久化到硬盘
- 消息确认机制:消费者处理消息后需要回复ACK,若迟迟未回复需要重发消息
- 消息重试机制:处理消息失败时,需要每隔几秒进行一次重试,多次重试失败可以发到死信队列,等待后续的人工处理或其他操作
接口幂等性:
- 唯一标识(幂等键):客户端为每个请求生成唯一ID,服务器校验唯一ID是否已处理、待处理
- 数据库乐观锁:比如where status=unpaid,在数据库层面保证幂等性
- 数据库唯一约束:利用唯一索引防止数据重复写入,尤其是insert
- 消息去重:生产者为每一条消息添加唯一的消息ID,消费者先判断是否已处理
消息积压: 根本原因是消费者效率低
- 排查消费者逻辑业务,是否有线程饥饿等不良代码发生,优化消费代理逻辑
- 水平扩容,同步增加队列数和消费者数
- 如已经大量积压
- 1.新建一个Queue数量充分的临时Topic
- 2.写一个用于分发消息的消费者程序,轮询的将旧Topic中的消息分发到新Topic中
- 3.调用能够支持相应生产力的消费者机器进行消费
- 绝招:先将消息进行持久化或转入死信队列进行后续补偿
MQ是如何保证消息一致性:
1.生产者发送消息给MQ
2.MQ将消息持久化到磁盘或数据库中
3.完成持久化后MQ返回ACK给生产者
4.MQ将消息推送给消费者
5.消费者完成消费后返回ACK给MQ
6.MQ确认ACK消息,从存储系统中删除已消费的消息
MQ如何保证消息事务:
1.生产者发送消息给MQ
2.MQ持久化到存储系统中,此时消息状态为待推送
3.MQ返回ACK给生产者,生产者进行事务的提交
4.事务若提交成功,通知MQ,MQ将消息状态由待推送改为可推送,若事务提交失败则回滚,通知MQ删除消息
5.如果MQ长时间未收到生产者的事务通知,则会查询生产者的事务结果来执行[补偿机制]
tips:生产者端必须通过事务消息,而消费者端可以不用。因为对于消费者来说,消息已经在MQ中了,跑不了。而生产者如果只是简单的重发消息,万一中途挂了就消失了
RabbitMQ的交换机类型:为RabbitMQ特有
- 直连交换机:精准匹配,只有路由键完全一样才会进行转发
- 扇形交换机:采用广播模式,只要这个队列绑定了这个交换机,就会直接转发消息
- 主题交换机:路由键模糊匹配,比如所有以order开头的消息
死信队列:
- 问题消息或无法处理的消息会进入死信队列
- 队列爆满时,最老的消息就会进入死信队列
- 特殊场景:
- 超时未支付:用户在规定时间内支付了就发往消费者,否则发往死信队列,后续消费者根据私信队列的消息进行订单删除



