RabbitMQ消息队列(一)

210 阅读5分钟

什么是消息中间件?

MQ全称为Message Queue,消息队列是应用程序和应用程序之间的通信方法。

消息队列的应用场景

MQ的优势

服务解耦

image.png 使用MQ后,消息通过中间件转发,消费者从MQ中取消息,如果库存系统出现异常,等库存系统自我修复后再去MQ中取消息,不会影响其他系统。添加新系统也是去MQ中取,不用修改订单系统的代码。

异步处理

image.png 使用MQ,一个订单只需要25ms,提升用户体验和系统的吞吐量(QPS:单位时间内处理请求的数目)

流量削峰

image.png

  • 消息被MQ保存起来了,然后系统就可以按照自己的消费能力来消费,比如每秒1000个数据,这样慢慢写入数据库,这样就不会卡死数据库了。
    可以起到一个缓冲的作用,防止短时间内大量请求导致数据库宕机系统崩溃,将数据发先发送至消息队列压积,然后拉去一定数量的数据进行处理,防止请求峰值时期大量的请求直接发送到数据库导致系统崩溃。

MQ的劣势

  • 系统可用性降低

系统引入的外部依赖越多,系统稳定性越差。一旦 MQ 宕机,就会对业务造成影响。如何保证MQ的高可用?

  1. 集群部署:通过将多个 RabbitMQ 节点组成一个集群,实现数据的自动复制和故障转移,从而提高可用性。
  2. 镜像队列:RabbitMQ 支持镜像队列(Mirrored Queue),可以将队列的消息复制到多个节点上,从而保证在某个节点宕机的情况下,仍然能够正常处理消息。
  3. 负载均衡:通过在 MQ 客户端和服务器之间引入负载均衡器,将请求分配到多个 MQ 节点上,从而提高系统的可用性和性能。
  4. 容灾备份:对于重要的 MQ 数据,可以进行容灾备份,将数据备份到多个地方,确保在某个地方发生灾难性事件的情况下,仍然能够快速地恢复数据。
  • 系统复杂度提高

MQ 的加入大大增加了系统的复杂度,以前系统间是同步的远程调用,现在是通过 MQ 进行异步调用。如何保证消息没有被重复消费?怎么处理消息丢失情况?怎么保证消息传递的顺序性?

  1. 消息重复消费的问题:可以通过以下两种方式来避免消息重复消费:

    • 消息幂等性(幂等性:无论你重复请求多少次,得到的结果都是一样的):在消费者端,对于相同的消息,无论消费多少次都只会产生一次业务效果,即不会引起重复处理的问题。可以通过在消息体中添加唯一的消息 ID 或者在业务逻辑中进行幂等性处理等方式来实现。
    • 消费者端去重:可以根据消息 ID 进行去重,消费者端可以通过维护一个已经处理过的消息列表来避免重复消费。当消费者接收到消息后,首先检查该消息是否已经在列表中出现过,如果是,则直接忽略该消息。
  2. 消息丢失的问题:消息丢失的主要原因是消息在传递过程中出现了错误,例如网络故障、节点宕机等。为了避免消息丢失,可以采用以下两种方式:

    • 消息持久化:在 RabbitMQ 中,可以将消息设置为持久化,确保即使 MQ 宕机,消息也不会丢失。同时,在消费端,需要使用 ACK 机制,确保消息已经被正确消费,避免消息丢失。
  3. 消息传递顺序的问题:由于 RabbitMQ 是异步处理消息的,因此无法保证消息的传递顺序。如果需要保证消息的顺序性,可以采用以下两种方式:

    • 单一队列:将所有需要按顺序处理的消息都发送到同一个队列中,由同一个消费者消费,可以通过设置队列的消费者数为 1,可以确保消息按照生产者的顺序被处理。
    • 有序队列:有序队列是 RabbitMQ 的一个插件,可以确保按照特定的顺序处理消息。在使用有序队列时,需要为每个队列分配一个序号,消息按照序号依次处理。
  • 一致性问题

A 系统处理完业务,通过 MQ 给B、C、D三个系统发消息数据,如果 B 系统、C 系统处理成功,D 系统处理 失败。如何保证消息数据处理的一致性。 使用mq中只能保证最终一致性。
最终一致性是指在一定时间内,系统最终会达到一致的状态,但在此期间可能存在一段时间的不一致。 消息队列(MQ)本身并不能保证数据一致性,因为它们是异步传递消息的。异步传递意味着发送方将消息发送到队列中,而接收方将在稍后的时间点收到并处理该消息。在这个过程中,发送方和接收方之间的数据可能会发生不一致的情况,例如发送方在消息发送之后立即崩溃,而接收方还没有来得及处理该消息。