RabbitMQ
MQ如何保证消息可靠性?如何保证消息不丢失?
生产者:
- 开启重试策略,保证消息正确到达MQ,如果重试次数耗尽,则写入数据库,后期交由人工处理
- 开启confirm机制,保证消息正确到达交换机
- 开启return机制,保证消息正确到达队列
持久化操作:
- 创建交换机、队列、消息时设置持久化(默认就是持久化),保证MQ宕机后重启不丢失
消费者:
- 开启自动ack,并且设置本地重试策略,当本地重试次数耗尽后,失败消息路由到错误队列。
- 监听错误队列,把消息写入数据库,后期交由人工处理
消费者的操作是否是一个幂等性操作?
天生幂等的操作:一般不管 非幂等性操作
- 消费者先从Redis中获取消息ID,如果存在,则表示有人在消费消息,我什么都不做。如果不存在,表示是该消息是第一次被消费,正常消费,并且向存储Key为消息ID的数据到Redis,同时设置过期时间
- 业务判断:由一个状态到另一个状态,必须加条件是初始状态
- MQ可靠性保证并不是100%,所以有可能消费者没有收到MQ的消息,那么后续就无法执行了。我们可以主动发起查询去获取最新结果,然后继续完成后面的业务操作
多个消费者,如何保证消息的顺序消费?
消费者指定线程消费数为1
MQ增加队列属性为 x-single-active-consumer 为true
- 表示当前队列,只能同时有一个消费者消费消息
消息积压问题
1、首先:消息积压的原因,大部分情况是消费者消费速度 跟不上生产者生产速度
2、这种情况下,我们可以采用惰性队列先将生产的消息存入磁盘,在消费时再加载到内存。以此来缓解队列存储消息的压力
3、分析积压消息的原因,大概率是消费者出问题了。那么首先先修复消费者代码、启动消费者程序。然后再临时增加消费者程序节点,以倍速的形式去消费积压的消息,当积压的消息被处理的差不多的时候,再把增加的节点下线
死信交换机
成为死信的几种情况:
1、消费者使用basic.reject 或 basic.nack 声明消费失败,并且消息的requeue参数设置为false
2、消息设置了过期时间,或者消息存放的队列设置了过期时间,超时无人消费
3、要投递的队列消息满了,无法投递
这些就是死信,然后会通过路由规则经过交换机路由到一个队列,这个交换机就叫死信交换机,这个队列就是死信队列
与Kafka的区别
Kafka
- 优点:
1、吞吐量大
2、功能强大:处理流媒体 - 缺点:
1、时效性差:消息延迟时间比MQ长 - 特点:
1、重Topic:收发消息都必须指定Topic
2、拉模式:由消费者主动去Broker中拉取消息
3、消息消费完后,不会删除,保留历史消息
RabbitMQ
- 优点:
1、时效性强、可靠性高 - 缺点:
1、吞吐量比Kafka小 - 特点:
1、轻Topic:不同工作模式可以选择是否使用Topic
2、推模式:由Broker主动把消息推送给消费者
3、消息阅后即焚