#  一、消息队列介绍和使用场景

## 1、什么是消息队列？

消息队列中间件是分布式系统中重要的组件，主要解决应用耦合、异步消息、流量削锋等问题。实现高性能、高可用、可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。

市面上主流的消息队列有：ActiveMQ、RabbitMQ、ZeroMQ、Kafka、MetaMQ、RocketMQ等。

## 2、消息队列应用场景

场景分为异步处理、应用解耦、流量削锋和消息通讯四个场景。

### 2.1异步处理

```txt
场景说明：用户注册后，需要发送注册邮件和发送注册信息，传统的做法有两种：串行方式、并行方式
```

**串行方式：**

将注册信息写入数据库成功后，发送注册邮件，然后发送注册短信，而所有任务执行完成后，返回信息给客户端

![image-20200401173548661](https://cdn.jsdelivr.net/gh/rongweihe/ImageHost01/gzh/kafka01.png)

**并行方式：**

 将注册信息写入数据库成功后，同时进行发送注册邮件和发送注册短信的操作。而所有任务执行完成后，返回信息给客户端。同串行方式相比，并行方式可以提高执行效率，减少执行时间。 

![image-20200401204150702](https://cdn.jsdelivr.net/gh/rongweihe/ImageHost01/gzh/kafka02.png)

**使用消息队列：**

![image-20200401204251266](https://cdn.jsdelivr.net/gh/rongweihe/ImageHost01/gzh/kafka03.png)

根据上述的流程，用户的响应时间基本相当于将用户数据写入数据库的时间，发送注册邮件、发送注册短信的消息在写入消息队列后，即可返回执行结果，写入消息队列的时间很快，几乎可以忽略，也有此可以将系统吞吐量提升至20QPS，比串行方式提升近3倍，比并行方式提升2倍。

### 2.2应用解耦

```txt
场景说明：用户下单后，订单系统需要通知库存系统。
```

**传统方式：**

传统的做法为：订单系统调用库存系统的接口。如下图所示：

![image-20200401204804056](https://cdn.jsdelivr.net/gh/rongweihe/ImageHost01/gzh/kafka04.png)



 传统方式具有如下缺点：
-1. 假设库存系统访问失败，则订单减少库存失败，导致订单创建失败
-2. 订单系统同库存系统过度耦合 

**使用消息队列：**

![image-20200401204944168](https://cdn.jsdelivr.net/gh/rongweihe/ImageHost01/gzh/kafka05.png)

- 订单系统：用户下单后，订单系统进行数据持久化处理，然后将消息写入消息队列，返回订单创建成功
- 库存系统：使用拉/推的方式，获取下单信息，库存系统根据订单信息，进行库存操作。

假如在下单时库存系统不能正常使用。也不影响正常下单，因为下单后，订单系统写入消息队列就不再关心其后续操作了。由此实现了订单系统与库存系统的应用解耦。

### 2.3流量削峰

流量削锋也是消息队列中的常用场景，一般在秒杀或团抢活动中使用广泛。

```txt
应用场景：秒杀活动，一般会因为流量过大，导致流量暴增，应用挂掉。为解决这个问题，一般需要在应用前端加入消息队列。
```

1. 可以控制参与活动的人数；
2. 可以缓解短时间内高流量对应用的巨大压力, 服务器在接收到用户请求后，首先写入消息队列。这时如果消息队列中消息数量超过最大数量，则直接拒绝用户请求或返回跳转到错误页面；

### 2.4消息通讯

 消息通讯是指，消息队列一般都内置了高效的通信机制，因此也可以用在纯的消息通讯。比如实现点对点消息队列、聊天室等。 

**点对点通讯：**

![image-20200401205926315](https://cdn.jsdelivr.net/gh/rongweihe/ImageHost01/gzh/kafka06.png)

在点对点通讯架构设计中，客户端A和客户端B共用一个消息队列，即可实现消息通讯功能。

**聊天室通讯**：

![image-20200401210029429](https://cdn.jsdelivr.net/gh/rongweihe/ImageHost01/gzh/kafka07.png)

 客户端A、客户端B、直至客户端N订阅同一消息队列，进行消息的发布与接收，即可实现聊天通讯方案架构设计。 

## 3.消息队列的两种模式

### 3.1点对点模式

 一对一，消费者主动拉取数据，消息收到后消息清除 

```txt
消息生产者生产消息发送到Queue中，然后消息消费者从Queue中取出并且消费消息。消息被消费以后，queue 中不再有存储，所以消息消费者不可能消费到已经被消费的消息。Queue 支持存在多个消费者，但是对一个消息而言，只会有一个消费者可以消费
```

![](https://cdn.jsdelivr.net/gh/rongweihe/ImageHost01/gzh/kafka088.png)

### 3.2 发布/订阅模式 

一对多，消费者消费数据之后不会清除消息

```txt
消息生产者（发布）将消息发布到 topic 中，同时有多个消息消费者（订阅）消费该消息。和点对点方式不同，发布到 topic 的消息会被所有订阅者消费。
```

![image-20200401210727451](https://cdn.jsdelivr.net/gh/rongweihe/ImageHost01/gzh/kafka09.png)



## 4.市面上主流消息队列比较

 ![消息队列对比参照表](https://img-blog.csdnimg.cn/20190516132244754.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Z4YmluMTIz,size_16,color_FFFFFF,t_70) 