1. 为什么要用消息队列?

        消息队列MQ是一个中间件:负责把要传输的数据放在队列中。 JDK实现的队列种类虽然有很多种,但都是简单的内存队列,所以MQ还是必要的。

1.1 解耦

一个例子:系统A负责产生一个userId,系统B、C、D拿这个userId去做相关的操作。 系统A将userId写到消息队列中,系统C和D从消息队列中拿数据,这样系统A与系统B、C、D都解耦了(当系统B、C、D发生变化时,系统A都不用经常改动)。

java MQ接收消息乱码_开发语言

其好处如下:

  • 系统A只负责把数据写到队列中,谁想要或不想要这个数据(消息),A一点都不关心
  • 即便现在系统D不想要userId这个数据了,系统B又突然想要userId这个数据了,都跟系统A无关,A一点代码都不用改。
  • 系统D拿userId不再经过系统A,而是从消息队列里边拿。系统D即便挂了或者请求超时,都跟系统A无关,只跟消息队列有关。

1.2 异步

    为了提高用户体验和吞吐量,可以异步地调用系统B、C、D的接口。

java MQ接收消息乱码_消息队列_02

1.3 削峰/限流

一个削峰场景:每月一次大促,期间并发可能会很高(每秒3000个请求)。假设现有两台机器处理请求,且每台机器每次只能处理1000个请求。

java MQ接收消息乱码_java_03

        系统B、C根据自己能够处理的请求数去消息队列中拿数据,这样即便有每秒有8000个请求,那只是把请求放在消息队列中,从MQ拿多少消息由系统自己控制,就不会把整个系统给搞崩。

2. 使用消息队列有什么问题?

2.1 高可用

        无论使用消息队列来做解耦、异步还是削峰,MQ肯定不能是单机的,必须是集群/分布式的。

2.2 数据丢失问题

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

java MQ接收消息乱码_数据_04

 数据丢失问题:消息队列中的数据需要存储起来,尽可能减少数据的丢失。

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

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

  • 生产者将数据放到消息队列中,消息队列有数据了,主动叫消费者去拿(俗称push);
  • 消费者不断去轮询消息队列,看看有没有新的数据,如果有就消费(俗称pull)。

2.4 其他要考虑的问题

  • 消息重复消费?
  • 保证消息是绝对有顺序?

虽然MQ带来了那么多好处,但同时也会提高系统的复杂性