当前位置: 首页 > news >正文

Rabbit MQ知识总结

1.什么是Rabbit MQ?

Rabbit MQ是一个开源的消息代理软件,它实现了高级消息队列协议(AMQP);

基本概念

  1. 消息:消息是在应用程序之间传递的数据单元。可以是简单的文本信息,可以是复杂的对象。
  2. 队列:队列是消息的容器,用于存储消息。他就像一个等待处理的任务列表,消息以先进先出的方式在队列中被处理。
  3. 生产者消费者:生产者是创建和发送消息的应用程序或组件。消费者则是接收和处理消息的应用程序。

功能特点

  1. 可靠性高:Rabbit MQ使用持久化机制来确保消息不会丢失。消息可以被标记为持久化,这样Rabbit MQ服务器重启后,消息仍然可以被恢复。
  2. 灵活的消息分发策略:它支持多种消息分发模式。比如轮询模式,多个消费者可以轮流从队列种获取消息,确保每个消费者都能公平的处理消息;还有直接分发模式,根据消息特定的路由键(routing key)将消息发送到指定的队列,被对应的消费者处理。
  3. 支持多种协议:除了AMQP,Rabbit MQ还支持其他消息协议,比如STOMP,MQTT。使得它能够与多种不同类型的客户端和应用程序集成。
  4. 集群和高扩展性:Rabbit MQ可以构建集群来提供高可用和横向扩展性.通过在多个节点上部署Rabbit MQ,可以实现故障转移。比如一个节点出现故障,其他节点可以接管其工作,确保消息系统的持续运行。

应用场景

  1. 异步处理:在一些耗时的操作中,比如文件上传后的数据处理等,可以将任务消息发送到Rabbit MQ队列。消费者可以在后台异步处理这些任务,而不会影响用户其他操作,提高系统的响应速度。例如:用户在一个社交平台上传了一张照片,系统将照片转码任务放入 RabbitMQ 队列,用户可以继续浏览其他内容,同时转码任务在后台慢慢处理。
  2. 流量削峰:在高流量场景下,比如电商系统促销期间,订单量可能会突然暴增。通过将订单消息放入Rabbit MQ队列,后端系统可以按照自己的处理能力从队列种获取消息进行处理,避免后端系统被大量请求压垮。
  3. 解耦系统组件:当一个大型系统包含多个相互关联的子系统时,RabbitMQ 可以用于解耦这些子系统。例如,在电商系统中,订单系统、库存系统、支付系统等之间通过消息队列进行通信。订单系统产生订单消息后发送到队列,库存系统和支付系统作为消费者从队列中获取消息并进行相应的处理。这样,各个子系统之间不需要直接相互调用,降低了系统的耦合度,便于系统的维护和扩展。

2.RabbitMQ的七种工作模式

RabbitMQ的七种工作模式

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

  1. 单队列单消费者模式

    • 原理:将需要保证顺序的消息发送到同一个队列中,并且让这个队列只有一个消费者进行消费。这样消息按照进入队列的顺序被消费者获取,自然就保证了消息的顺序性。
    • 示例:假设有一个订单处理系统,订单的创建、支付、发货等消息是有严格顺序要求的。可以将这些和同一个订单相关的消息发送到名为 “订单队列” 的队列中,并且只启动一个消费者来处理这个队列中的消息。
    • 缺点:这种方式的性能和可用性相对较低,因为单个消费者可能会成为性能瓶颈,而且如果消费者出现故障,消息处理就会中断。
  2. 拆分多个队列并保证顺序消费

    • 原理:根据业务规则,将消息划分到不同的队列中,每个队列中的消息都有顺序要求,并且在每个队列上只配置一个消费者来保证顺序。
    • 示例:在一个电商系统中,对于不同类型的商品(如电子产品、服装、食品)的订单消息,可以分别发送到 “电子产品队列;衣服队列;食物队列” 等不同的队列中。每个队列都有自己单独的消费者,这样就可以在不同的商品类型内部保证订单消息的顺序。
    • 局限性:需要对业务有很好的理解,合理地划分队列,并且当业务规则发生变化时,可能需要重新调整队列的划分。
  3. 消息分组和局部顺序性保证

    • 原理:在消息中添加分组标识,消费者根据分组标识来处理消息,保证同一组内的消息顺序。在 RabbitMQ 中,可以通过消息的属性或者消息体中的自定义字段来添加分组标识。
    • 示例:假设有一个消息包含用户的操作记录,如登录、浏览商品、添加购物车等。可以在消息体中添加一个用户 ID 作为分组标识。消费者接收到消息后,先按照用户 ID 对消息进行分组,然后在每个用户组内按照消息的顺序进行处理,这样就可以保证每个用户的操作记录是按照顺序处理的。
    • 注意点:消费者需要有额外的逻辑来进行分组和顺序控制,增加了消费者的复杂性。同时,在高并发情况下,需要注意分组消息的存储和排序效率。
  4. 使用事务和消息确认机制结合

    • 原理:在生产者端,使用事务来确保消息按照顺序发送到队列。在消费者端,结合消息确认机制,只有当一条消息处理完成并且符合顺序要求后,才确认该消息,然后再处理下一条消息。
    • 示例:在生产者发送消息时,开启一个事务,将多条有顺序要求的消息依次发送到队列中。如果发送过程中出现问题,事务可以回滚,保证消息不会乱序发送。消费者在接收到消息后,只有在正确处理完当前消息并且下一条消息符合顺序要求时,才发送消息确认,这样可以防止消息的无序消费。
    • 缺点:使用事务会增加系统的开销,影响性能,并且需要仔细处理事务的边界和异常情况。
  5. 通过消息优先级辅助保证顺序性(在一定程度上)

    • 原理:RabbitMQ 支持消息优先级。如果消息有顺序要求,可以为消息设置优先级,按照优先级顺序发送和消费消息。不过这种方法不能完全保证顺序性,只是在一定程度上辅助保证顺序。
    • 示例:在一个新闻发布系统中,对于重要新闻的更新消息(如头条新闻)可以设置较高的优先级,其他普通新闻更新消息设置较低的优先级。在消费者端,优先处理高优先级的消息,并且在优先级相同的消息之间,按照发送顺序进行处理,这样可以在一定程度上保证重要新闻更新的顺序性。

4.如何保证消息消费时的幂等性(消息不被重复消费)? 

  1. 什么是消息的幂等性

    • 幂等性是指对同一个操作的一次请求和多次重复请求对系统资源的影响是一致的。在消息消费场景中,就是指无论消息被消费多少次,对系统产生的最终效果和只消费一次是相同的。
  2. 利用数据库的唯一约束保证幂等性

    • 原理:当消息被消费时,需要将消息的关键信息(如消息 ID、业务唯一标识等)插入到数据库中。如果数据库表中该字段设置了唯一约束,那么当重复消息消费导致插入相同的标识时,数据库会抛出异常,通过捕获这个异常就可以避免重复消费。
    • 示例:在一个用户注册系统中,当接收到用户注册的消息时,将用户的手机号码作为唯一标识插入到 “user_registration” 表中。如果消息重复消费,第二次插入相同手机号码时会违反唯一约束,此时就可以识别出这是重复消息,不再进行实际的注册操作。
    • 注意点:这种方法可能会影响数据库性能,因为每次消息消费都涉及数据库操作。同时,需要合理设计数据库表结构和唯一约束字段,确保能够准确识别重复消息。
  3. 使用状态机实现幂等性

    • 原理:为业务流程设计一个状态机,每个消息的消费会使业务状态发生变化。在消费消息时,先检查当前业务状态是否符合消息消费的预期状态,如果不符合则说明消息可能已经被消费过,不再进行处理。
    • 示例:在一个订单处理系统中,订单有 “已创建”“已支付”“已发货”“已完成” 等状态。当消费支付消息时,先检查订单状态是否为 “已创建”,如果是,则进行支付处理并将订单状态更新为 “已支付”;如果订单状态不是 “已创建”,则说明支付消息可能已经被处理过,不再进行重复支付操作。
    • 局限性:需要准确地设计和维护状态机,状态转换规则复杂时可能会出现错误。并且当业务状态被其他因素(如人工干预)修改时,可能会影响状态机的正常判断。
  4. 基于消息的唯一标识进行去重

    • 原理:消息本身通常有一个唯一的消息 ID,或者可以在消息体中添加自定义的唯一标识。在消息消费者端,维护一个已消费消息 ID 的集合(可以是内存中的集合、缓存或者数据库存储),当接收到消息时,先检查消息 ID 是否在已消费集合中,如果在则忽略该消息,不在则进行消费并将消息 ID 添加到集合中。
    • 示例:使用 Redis 的 Set 数据结构来存储已消费的消息 ID。在消息消费者中,每次接收到消息时,使用 Redis 的 SISMEMBER 命令检查消息 ID 是否在集合中。如果不在,进行消息消费并使用 SADD 命令将消息 ID 添加到集合中。
    • 注意点:需要考虑存储已消费消息 ID 的存储介质的性能和可靠性。如果使用内存存储,当消费者重启时可能会丢失数据;如果使用数据库存储,会增加数据库的读写操作。同时,对于高并发的场景,需要注意存储和查询操作的效率。
  5. 通过消息确认机制实现幂等性(结合消息中间件特性)

    • 原理:在消息中间件(如 RabbitMQ)中,消息消费成功后需要向中间件发送确认消息。如果消息没有被正确确认,中间件可能会重新发送消息。在消费者端,可以通过记录消息的消费状态和确认状态来避免重复消费。
    • 示例:在消费者内部维护一个消息消费状态表,记录消息 ID、消费状态(未消费、已消费未确认、已确认)等信息。当接收到消息时,先检查消费状态,如果是 “已确认” 则忽略该消息;如果是 “未消费” 则进行消费并将状态更新为 “已消费未确认”,在成功消费后发送确认消息给中间件,并将状态更新为 “已确认”。
    • 复杂性:这种方法需要消费者自己维护消息消费状态,增加了消费者的复杂性。并且需要确保消息确认机制和消费状态更新的原子性,避免出现不一致的情况。

5.如何保证RabbitMQ消息的可靠传输?

  1. 生产者可靠发送
    • 使用发送方确认模式(publisher confirm)
      • 原理:发送方确认模式是一种更高效的方式来确保消息发送的可靠性。当生产者开启这个模式后,每发送一条消息,RabbitMQ 服务器会返回一个确认(ack)消息给生产者。如果生产者没有收到确认消息,就可以认为消息发送失败,从而进行重试或其他错误处理。
      • 注意点:虽然发送方确认模式比事务机制性能更好,但在高并发场景下,生产者需要合理处理确认消息,避免因为等待确认而导致性能瓶颈。
      • 开启事务机制
        • 原理:在 RabbitMQ 中,生产者可以使用事务来确保消息的可靠发送。开启事务后,生产者发送消息的操作会被包含在一个事务块中。如果消息成功发送到队列,事务就可以提交;如果发送过程中出现任何问题,如网络故障、队列不存在等,事务可以回滚,保证消息不会丢失。
        • 缺点:事务机制会带来较大的性能开销,因为它涉及到与 RabbitMQ 服务器的多次交互,包括开启事务、提交或回滚事务等操作。

2.消息持久化

  • 队列持久化
    • 原理:在 RabbitMQ 中,可以将队列设置为持久化。持久化的队列会在 RabbitMQ 服务器重启后依然存在,确保消息不会因为队列的丢失而丢失。当创建队列时,将队列的属性设置为持久化(durable = true)即可。
  • 消息持久化
    • 原理:除了队列持久化,还需要将消息设置为持久化。这样,当 RabbitMQ 服务器发生意外情况(如断电、重启等)时,消息能够在服务器恢复后依然存在。在发送消息时,将消息的属性设置为持久化(MessageProperties.PERSISTENT_TEXT_PLAIN)。
  • 局限性:消息持久化会增加一定的性能开销,因为 RabbitMQ 需要将消息写入磁盘来保证持久化。而且在极端情况下,如磁盘损坏,消息依然可能丢失。

3.消费者可靠接收

  • 自动消息确认和手动消息确认
    • 原理:RabbitMQ 默认是自动消息确认模式,消费者一旦接收到消息,就会自动向 RabbitMQ 服务器发送确认消息,然后消息就会从队列中删除。但这种方式可能会导致消息丢失,例如消费者在处理消息的过程中出现故障。手动消息确认模式则可以让消费者在成功处理完消息后再发送确认消息,这样可以确保消息不会丢失。
  • 消息预取(QoS)
    • 原理:通过设置消息预取(Quality of Service,QoS),可以限制消费者一次接收的消息数量。这样可以防止消费者接收过多的消息而无法及时处理,导致消息积压或者丢失。例如,设置 QoS 为 1,消费者一次只会接收一条消息,只有在处理完这条消息并确认后,才会接收下一条消息。

6.RabbitMQ的其他知识

 重试机制 死信队列

http://www.lryc.cn/news/508483.html

相关文章:

  • 未来将要被淘汰的编程语言
  • GO环境安装和配置
  • 面试题整理(四)
  • mathtype中如何在公式和序号之间加点
  • 【电源专题】电源芯片的PG(Power Good)管脚是什么?
  • C/C++圣诞树
  • 牛客--求小球落地5次后所经历的路程和第5次反弹的高度,称砝码
  • cad学习 day6
  • Chrome 浏览器插件获取网页 iframe 中的 window 对象
  • 免费线上签字小程序,开启便捷电子签名
  • IT运维的365天--021 服务器上的dns设置后不起作用
  • 深信服企业级数据备份与恢复系统(整机裸机恢复)
  • Tool之Excalidraw:Excalidraw(开源的虚拟手绘风格白板)的简介、安装和使用方法、艾米莉应用之详细攻略
  • OPPO C++面试题及参考答案
  • Unity中LineRenderer使用MeshCollider方法参考
  • BERT模型入门(1)BERT的基本概念
  • 致命错误: Class ‘ZipArchive‘ not found
  • 二手车交易平台开发:安全与效率的双重挑战
  • vector题目
  • 测试测试测试测试测试测试测试测试测试测试
  • Cisco WebEx 数据平台:统一 Trino、Pinot、Iceberg 及 Kyuubi,探索 Apache Doris 在 Cisco 的改造实践
  • 大恒相机开发(3)—大恒相机工业检测的实际案例
  • 【泛微表单】流程相关信息修改
  • LeetCode80.删除有序数组的重复项
  • rk3568制冷项目驱动开发流程汇总(只适用于部分模块CIF DVP等,自用)
  • 费舍尔信息矩阵全面讲述
  • DALFox-一款XSS自动化扫描工具
  • Python 异步协程:从 async/await 到 asyncio 再到 async with
  • 云原生周刊:利用 eBPF 增强 K8s
  • 【pycharm】远程服务器之后如何打开终端