RabbitMQ介绍

什么是RabbitMQ?

RabbitMQ是一款开源的,Erlang编写的,消息中间件; 最大的特点就是消费并不需要确保提供方 存在,实现了服务之间的高度解耦 可以用它来:解耦、异步、削峰。

解耦是指将系统的不同部分或功能解开,使其能够独立地进行开发、维护和扩展。通过解耦,系统中的各个组件或模块可以独立地进行修改或替换,而不会对其他组件或模块产生影响。

解耦主要两方面:

1.生产消息的应用 和 消费消息的应用不是同一种语言可以解耦

2.生产消息的应用 宕机,不会影响到消费者消费消息

异步是指系统中的某个操作或任务可以在后台执行,而不会阻塞其他操作或任务的进行。通过异步处理,系统可以更好地利用资源,提高响应速度和吞吐量。例如,异步处理可以通过多线程、多进程、消息队列等方式实现。

削峰是指在系统负载过高时,采取措施来平抑负载的峰值,以保证系统的稳定性和可靠性。削峰可以通过多种手段实现,如引入缓存、负载均衡、流量控制等。削峰的目的是在高负载情况下,尽量避免系统性能下降或崩溃。

rabbitmq 的使用场景

(1)服务间异步通信 (2)顺序消费 (3)定时任务 (4)请求削峰

RabbitMQ基本概念

  • Producer- 生产者:发布消息到RabbitMQ中的Exchange

  • Consumer - 消费者:监听RabbitMQ中的Queue中的消息

  • Exchange - 交换机:和生产者建立连接并接收生产者的消息

  • Queue - 队列:Exchange会将消息分发到指定的Queue,Queue和消费者进行交互

  • Routes - 路由:交换机以什么样的策略将消息发布到Queue

RabbitMQ的使用【重点


 工作模式

 

如何保证RabbitMQ消息的顺序性?

拆分多个 queue(消息队列),每个 queue(消息队列) 一个 consumer(消费者),就是多一些 queue (消息队列)而已,确实是麻烦点; 或者就一个 queue (消息队列)但是对应一个 consumer(消费者),然后这个 consumer(消费者)内部用内存队列做排队,然后分发给底层不同的 worker 来处理

配置消息的ack 机制

ack 机制的意义:就是保证消费者真的收到了消息,并且完成了该消息对应业务之后,

回复ack 确认真正的处理了该消息对应的业务。

没有回复ack,队列会继续发送此消息,直到消费者 ack 当前消息

如何保证rabbitmq 消息不丢失问题?

  • ack机制

  • confirm机制

  • return机制

嗯!我们当时MYSQL和Redis的数据双写一致性就是采用RabbitMQ实现同步的,这里面就要求了消息的高可用性,我们要保证消息的不丢失。主要从三个层面考虑

第一个是开启生产者确认机制,确保生产者的消息能到达队列,如果报错可以先记录到日志中,再去修复数据

第二个是开启持久化功能,确保消息未消费前在队列中不会丢失,其中的交换机、队列、和消息都要做持久化

第三个是开启消费者确认机制为auto,由spring确认消息处理成功后完成ack,当然也需要设置一定的重试次数,我们当时设置了3次,如果重试3次还没有收到消息,就将失败后的消息投递到异常交换机,交由人工处理

如何保证消息的不重复问题?

如何保证消息的不重复问题?

1.为每一条消息配置唯一标记id

2.在消费者端配置 ,如果消息还未被处理就开始处理,并做对应该消息标记id 做标记 0,如果消息对应业务已经被处理完成,则标记消息为 1

3.使用redis 的setnx 实现

嗯,这个我们还真遇到过,是这样的,我们当时消费者是设置了自动确认机制,当服务还没来得及给MQ确认的时候,服务宕机了,导致服务重启之后,又消费了一次消息。这样就重复消费了

因为我们当时处理的支付(订单|业务唯一标识),它有一个业务的唯一标识,我们再处理消息时,先到数据库查询一下,这个数据是否存在,如果不存在,说明没有处理过,这个时候就可以正常处理这个消息了。如果已经存在这个数据了,就说明消息重复消费了,我们就不需要再消费了

其实这个就是典型的幂等的问题,比如,redis分布式锁、数据库的锁都是可以的解决的

造成消息重复的根本原因是:网络不可达。 所以解决这个问题的办法就是绕过这个问题。那么问题就变成了:如果消费端收到两条一样的消 息,应该怎样处理? 消费端处理消息的业务逻辑保持幂等性。只要保持幂等性,不管来多少条重复消息,最后处理的结 果都一样。保证每条消息都有唯一编号且保证消息处理成功与去重表的日志同时出现。利用一张日 志表来记录已经处理成功的消息的 ID,如果新到的消息 ID 已经在日志表中,那么就不再处理这条 消息

RabbitMQ中死信交换机 ? (RabbitMQ延迟队列有了解过嘛)

如果消息超时未消费就会变成死信,在RabbitMQ中如果消息成为死信,队列可以绑定一个死信交换机,在死信交换机上可以绑定其他队列,在我们发消息的时候可以按照需求指定TTL的时间,这样就实现了延迟队列的功能了。

我记得RabbitMQ还有一种方式可以实现延迟队列,在RabbitMQ中安装一个死信插件,这样更方便一些,我们只需要在声明交互机的时候,指定这个就是死信交换机,然后在发送消息的时候直接指定超时时间就行了,相对于死信交换机+TTL要省略了一些步骤

如果有100万消息堆积在MQ , 如何解决 ?

第一:提高消费者的消费能力 ,可以使用多线程消费任务

第二:增加更多消费者,提高消费速度

使用工作队列模式, 设置多个消费者消费消费同一个队列中的消息

第三:扩大队列容积,提高堆积上限

可以使用RabbitMQ惰性队列,惰性队列的好处主要是

①接收到消息后直接存入磁盘而非内存

②消费者要消费消息时才会从磁盘中读取并加载到内存

③支持数百万条的消息存储

那出现丢数据怎么解决呢?

我们可以采用仲裁队列,与镜像队列一样,都是主从模式,支持主从数据同步,主从同步基于Raft协议,强一致。

并且使用起来也非常简单,不需要额外的配置,在声明队列的时候只要指定这个是仲裁队列即可

  1. 持久化消息:RabbitMQ 默认情况下消息是非持久化的,即消息在服务器重启后会丢失。可以在发送消息时设置消息的持久化属性,确保消息在服务器重启后能够恢复。同时,确保消费者消费消息时也使用了持久化的方式。

  2. 确认机制:消费者在消费消息后,可以发送一个确认消息给 RabbitMQ,告知 RabbitMQ 已经成功接收和处理了消息。RabbitMQ 在收到确认消息后才会移除消息,确保消息不会丢失。可以使用手动确认模式(manual acknowledgements)来控制确认消息的发送。

  3. 设置消息过期时间:可以为消息设置一个过期时间,在消息过期后自动将消息丢弃。这样可以防止消息在队列中永远占有空间,导致队列拥堵。

  4. 增加队列的容量:如果队列容量较小,可能会导致队列满了之后新的消息无法入队,从而丢失数据。可以考虑增加队列的容量,确保队列能够存储更多的消息。

  5. 设置备份队列:可以设置备份队列(alternate exchange),当主队列出现问题时,消息可以发送到备份队列,避免数据丢失。

  6. 设置消息持久性、消息确认、消息过期时间、队列持久性等配置参数:在创建队列和发送消息时,可以设置一些配置参数,如消息持久性、消息确认模式、消息过期时间、队列持久性等,以增加消息的可靠性和避免数据丢失。

  7. 监控和报警:设置监控和报警机制,及时发现和处理消息丢失的问题。可以通过监控 RabbitMQ 的各项指标,如队列消息数量、消费者数量、发布者速率等,一旦出现异常情况,则触发报警通知。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值