RabbitMQ的使用场景
rabbitMQ消息队列可以用来
- 做任务的异步处理,提高程序的相应时间
- 提高系统稳定性,通过手动确认机制,当消费者出现故障,只要没有确认签收,请求的数据都不会丢失可以再次处理
- 服务解耦,生产者通过MQ与消费者交互
- 消除峰值,通过异步处理,消息传到MQ直接返回,接着等待排队处理,避免了线路拥堵
RabbitMQ如何防止消息丢失
首先,RabbitMQ的消息确认机制,默认是自动签收,也就是说消息一旦被消费者接收,就自动签收,消息就从队列里清除了。因此对于重要的消息,不容丢失的数据,我们需要设置在消费完成后手动签收
其次,我们可以将消息持久化,交换机和队列都可以做持久化,也可以将消息入库,避免消息在消费前MQ宕机,网络问题等造成的消息丢失
RabbitMQ的交换机有哪几种
Fanout:广播,将消息交给所有绑定到交换机的队列
Direct:定向,把消息交给符合指定routing key的队列
Topic:通配符,把消息交给符合routing pattern的队列
消息是如何从发送者到达消费者的(RabbitMQ工作流程)
分为消息发送和消息接收两个步骤
- 消息发送:生产者和Broker建立TCP连接,创建信道。通过信道将消息发送给Broker,由Exchange将消息进行转发到指定的队列
- 消息接收:消费者和Broker建立TCP连接 ,创建信道 ,然后监听指定的队列,当有消息到达队列时,Broker默认将消息推送给消费者,消费者就能接收到消息
如何防止消息重复消费
重复消费,一般时由于消费者消费成功后,在给MQ确认签收的时候出现了网络波动,MQ没有接到确认,就会继续给消费者投递之前的消息,造成消费者接收到了两条一样的消息。
我们可以通过实现消息的幂等性来避免这种情况,比如说让生产者给每个消息携带一个唯一的id,消费者获取消息后根据这个id去查询数据库,如果不存在就正常消费,如果存在了就证明该消息被消费过,直接丢弃
RabbitMQ消息投递失败,你们怎么处理
我们可以设置confirm回调和 returned 回调
比如说,可以在发送消息的时候,把消息详情包括交换机名,路由键,都保存到一个表中,状态设置为发送中,如果在confirm方法中ack为false,代表发送到交换机失败 ,就把这个记录状态修改为发送失败
然后我们创建一个定时任务定时扫表,去读取发送失败的数据并重新发送,为了优化性能,我们设置重试次数3次,如果3次都失败了,我们可以采取人工干预