• 08-RabbitMQ使用中的常见问题


    一、RabbitMQ如何保证消息不丢失
    1、哪些环节存在消息丢失的可能

    因为1、2、4都是跨网络的,而跨网络就会存在丢失消息的可能。对于3来说,通常MQ存盘时都会先写入操作系统的缓存page cache中,然后再由操作系统异步寸盘。当在异步存盘时如果服务挂了,缓存中还未存盘的消息就会丢失。这是大部分应用程序无法避免的。
    对于任何MQ产品,都应该从这四个方面来考虑数据的安全性。

    2、RabbitMQ消息零丢失方案
    (1)生产者保证消息正确发送到RibbitMQ

    • 同步确认:通过在生产者端使用Channel.waitForConfirmsOrDie(5000)指定一个等待确认的完成时间,这个方法会在channel端等待RabbitMQ给出一个响应,用来表明这个消息已经正确发送到了RabbitMQ服务端,如果超过了这个时间,还没有收到服务端的确认机制,那就会抛出异常。也支持批量确认,但是不确定是哪个消息出问题的。此方法会同步阻塞channel,影响效率。
    • 异步确认:通过channel.addConfirmListener(ConfirmCallback var1, ConfirmCallback var2)在生产者端注入两个回调确认函数。第一个函数是在生产者发送消息时调用,第二个函数则是生产者收到Broker的消息确认请求时调用。需要客户端通过RabbitMQ对消息生成的sequenceNumber自行完成消息的前后对应。
    • 手动事务:channel.txSelect() 开启事务,channel.txCommit() 提交事务;channel.txRollback() 回滚事务;这种方式需要手动控制事务逻辑,并且手动事务会对channel产生阻塞,造成吞吐量下降

    (2)RabbitMQ消息存盘不丢消息
    对于Classic经典队列,直接将队列声明成为持久化队列即可。而新增的Quorum队列和Stream队列,都是明显的持久化队列,能更好的保证服务端消息不会丢失。

    (3)RabbitMQ主从消息同步时不丢消息
    如果是镜像模式集群,数据会主动在集群各个节点当中同步,丢失消息的概率不会太高。
    如果是普通集群模式,消息是分散存储的,不会主动进行消息同步,是有可能丢失消息的。
    可以通过配置autoheal以及启用Federation联邦机制,给包含重要消息的队列建立一个远端备份都可以解决。

    (4)RabbitMQ消费者不丢失消息
    RabbitMQ在消费消息时可以指定是自动应答,还是手动应答。如果是自动应答模式,消费者会在完成业务处理后自动进行应答,而如果消费者的业务逻辑抛出异常,RabbitMQ会将消息进行重试,这样是不会丢失消息的,但是有可能会造成消息一直重复消费。将RabbitMQ的应答模式设定为手动应答可以提高消息消费的可靠性。

    二、如何保证消息幂等
    RabbitMQ服务端:要设定RabbitMQ的重试次数,制定重试策略。因为当消费者消费消息处理业务逻辑时,如果抛出异常,或者不向RabbitMQ返回响应,默认情况下,RabbitMQ会无限次数的重复进行消息消费。
    消费端:处理幂等问题的关键是要给每个消息一个唯一的标识。在SpringBoot框架集成RabbitMQ后,可以给每个消息指定一个全局唯一的MessageID,在消费者端针对MessageID做幂等性判断。可以查库判断、或者借用布隆过滤器等redis高级数据结构。

    三、如何保证消息的顺序
    某些场景下,需要保证消息的消费顺序,例如一个下单过程,需要先完成扣款,然后扣减库存,然后通知快递发货,这个顺序不能乱。如果每个步骤都通过消息进行异步通知的话,这一组消息就必须保证他们的消费顺序是一致的。
    在RabbitMQ当中,针对消息顺序的设计其实是比较弱的。唯一比较好的策略就是单队列+单消息推送。即一组有序消息,只发到一个队列中,利用队列的FIFO特性保证消息在队列内顺序不会乱。然后在消费者进行消费时,保证只有一个消费者,同时指定prefetch属性为1,即每次RabbitMQ都只往客户端推送一个消息。但是这是以极度消耗性能作为代价的,在实际适应过程中,应该尽量避免这种场景
    而在多队列情况下,如何保证消息的顺序性,目前使用RabbitMQ的话,还没有比较好的解决方案。在使用时,应该尽量避免这种情况。

    四、RabbitMQ的数据堆积问题
    RabbitMQ一直以来都有一个缺点,就是对于消息堆积问题的处理不好。当RabbitMQ中有大量消息堆积时,整体性能会严重下降。目前新推出的Quorum队列以及Stream队列,目的就在于解决这个核心问题。但是这两种队列的稳定性和周边生态都还不够完善,因此在使用RabbitMQ时,还是要非常注意消息堆积的问题。尽量让消息的消费速度和生产速度保持一致。

    • 生产端:降低消息生产的速度,生产者端产生消息的速度通常是跟业务息息相关的,一般情况下不太好直接优化。尽量多采用批量消息的方式,降低IO频率。
    • RabbitMQ服务端:对于消息堆积严重的队列,可以预先添加懒加载机制,或者创建Sharding分片队列,这些措施都有助于优化服务端的消息堆积能力。尝试使用Stream队列,也能很好的提高服务端的消息堆积能力。
    • 消费端:增加消费者数量。对于单个消费者端,可以通过配置提升消费者端的吞吐量。(1)单次推送消息数量.(2)消费者的消费线程数量。灵活配置这两个参数,能够在一定程度上调整每个消费者实例的吞吐量,减少消息堆积数量。
    • 其他方式:换kafka

    五、RabbitMQ的备份与恢复

    • 对于元数据,可以在Web管理页面通过json文件直接导出或导入
    • 对于消息,可以手动进行备份恢复

    对于消息,由于MQ的特性,是不建议进行备份恢复的。
    恢复数据步骤:

    • 首先要保证要恢复的RabbitMQ中已经有了全部的元数据,这个可以通过上一步的json文件来恢复。
    • 然后备份过程必须要先停止应用。如果是针对镜像集群,还需要把整个集群全部停止。
    • 最后在RabbitMQ的数据目录中,有按virtual hosts组织的文件夹。只需要按照虚拟主机,将整个文件夹复制到新的服务中即可。持久化消息和非持久化消息都会一起备份。

    六、RabbitMQ的性能监控
    关于RabbitMQ的性能监控,在管理控制台中提供了非常丰富的展示。例如在下面这个简单的集群节点图中,就监控了非常多系统的关键资源,包括消息的生产消费频率、关键组件使用情况等信息。

    同时RabbitMQ也提供了一系列的HTTP接口,通过这些接口可以非常全面的使用并管理RabbitMQ的各种功能。在部署的管理控制台页面下方已经集成了详细的文档,只需要打开HTTP API的页面就能看到,通过这个接口,就可以很好的对接Promethus、Grafana等工具,构建更灵活的监控告警体系。

    七、搭建HAProxy,实现高可用集群
    之前搭建的镜像集群,已经具备了集群的功能,请求发送到任何一个节点上,数据都是在集群内共享的。但是在企业使用时,通常还会选择在集群基础上增加负载均衡的能力。将客户端的请求能够尽量均匀的分配到集群中各个节点上,这样可以让集群的压力得到平衡。
    实现负载均衡的方式有很多,HAProxy就是其中一种可选方案。HAProxy是一个免费、快速并且可靠的解决方案,有很多大型互联网公司都在使用。通过HAProxy,应用可以直连一个单一的IP地址,然后HAProxy会将这个IP地址的TCP请求进行转发,并在转发过程中实现负载均衡。

    除了HAProxy,还可采用Keepalived和F5,需要根据实际情况而定,适合的才是最好的

  • 相关阅读:
    “世界首台USB-C iPhone”被拍卖,目前出价63万人民币
    Django高级之-分页器
    LM1875L-TB5-T 音频功率放大器 PDF中文资料_参数_引脚图
    taro全局配置页面路由和tabBar页面跳转
    qiao-npms:搜索npm包
    力扣题库2. 两数相加
    第五章:抽象类
    我的创作纪念日--AI小怪兽打怪进阶路
    [FBCTF2019]RCEService
    vm2 组件存在沙箱逃逸漏洞
  • 原文地址:https://blog.csdn.net/qq_39234967/article/details/126295182