菜单

Administrator
发布于 2026-05-17 / 2 阅读
0
0

什么是消息队列

什么是消息队列

一篇文章告诉你什么是消息队列。我入门消息队列的笔记。
来源:mp.weixin.qq.com

一、什么是消息队列?

消息队列,一般我们会简称它为 MQ(Message Queue),就是很直白的简写。

我们先不管"消息(Message)“这个词,来看看"队列(Queue)”。队列是一种先进先出的数据结构。在 Java 里边,已经实现了不少队列了。

那为什么还需要消息队列(MQ)这种中间件呢??其实这个问题,跟之前我学 Redis 的时候很像。Redis 是一个以 key-value 形式存储的内存数据库,明明我们可以使用类似 HashMap 这种实现类就可以达到类似的效果了,那还为什么要用 Redis?

消息队列可以简单理解为:把要传输的数据放在队列中

科普:

  • 把数据放到消息队列叫做生产者
  • 从消息队列里边取数据叫做消费者

二、为什么要用消息队列?

2.1 解耦

现在我有一个系统A,系统A可以产生一个 userId,然后有系统B和系统C都需要这个 userId 去做相关的操作:

public class SystemA {

    // 系统B和系统C的依赖
    SystemB systemB = new SystemB();
    SystemC systemC = new SystemC();

    // 系统A独有的数据userId
    private String userId = "Java3y";

    public void doSomething() {
        // 系统B和系统C都需要拿着系统A的userId去操作其他的事
        systemB.SystemBNeed2do(userId);
        systemC.SystemCNeed2do(userId);
    }
}

某一天,系统B的负责人说不再使用了,于是系统A就得改代码删掉调用…

又过了几天,系统D的负责人说要使用 userId,系统A又得改代码…

每天被各种系统负责人骚扰,改来改去…

解决方案: 系统A将 userId 写到消息队列中,系统C和系统D从消息队列中拿数据。

好处:

  • 系统A只负责把数据写到队列中,谁想要或不想要这个数据,系统A一点都不关心
  • 即便系统D不想要了,系统B又突然想要了,都跟系统A无关,代码不用改
  • 系统D即使挂了或请求超时,都跟系统A无关,只跟消息队列有关

2.2 异步

系统A同步调用系统B、C、D:

public void doOrder() {
    userId = this.order();
    systemB.SystemBNeed2do(userId);  // 300ms
    systemC.SystemCNeed2do(userId);  // 300ms
    systemD.SystemDNeed2do(userId);  // 300ms
    // 共计:50 + 300 + 300 + 300 = 950ms
}

系统A做主要业务(订单下单),系统B/C/D是非主要业务(发短信等)。

解决方案: 系统A执行完以后,将 userId 写到消息队列中,然后直接返回。其它操作异步处理。

效果: 从 950ms 降为 100ms(异步)

2.3 削峰/限流

大促期间并发量高,比如每秒 3000 个请求。假设只有两台机器,每台每次只能处理 1000 个请求。

多余的 1000 个请求可能把整个系统搞崩。

解决方案: 写到消息队列中。系统B和系统C根据自己的处理能力去消息队列中拿数据,这样即使 8000 个请求,也只是把请求放在消息队列里,由系统自己控制,不会把整个系统搞崩。

三、使用消息队列有什么问题?

3.1 高可用

无论用消息队列来做解耦、异步还是削峰,消息队列肯定不能是单机的。单机消息队列挂了,那整个系统几乎就不可用了。

所以,消息队列都是得集群/分布式的。

3.2 数据丢失问题

我们将数据写到消息队列上,系统B和C还没来得及取消息队列的数据,就挂掉了。如果没有任何措施,我们的数据就丢了。

学过 Redis 的都知道,Redis 可以将数据持久化到磁盘上。同样地,消息队列中的数据也需要存在别的地方:

  • 磁盘?
  • 数据库?
  • Redis?
  • 分布式文件系统?
  • 同步存储还是异步存储?

3.3 消费者怎么得到消息队列的数据?

  • push:生产者将数据放到消息队列中,消息队列有数据了,主动叫消费者去拿
  • pull:消费者不断去轮询消息队列,看看有没有新的数据

3.4 其它问题

  • 消息重复消费了怎么办?
  • 想保证消息是绝对有顺序的怎么做?

虽然消息队列给我们带来了很多好处,但同时引入消息队列也会提高系统的复杂性。市面上已经有不少消息队列了,每种都有各自的特点,选取哪种 MQ 还得好好斟酌。


评论