消息队列的概念和原理

消息队列

  • 一、使用消息队列的场景
    • 1.1、消息队列的异步处理
    • 1.2、消息队列的流量控制(削峰)
    • 1.3、消息队列的服务解耦
    • 1.4、消息队列的发布订阅
    • 1.5、消息队列的高并发缓冲
  • 二、消息队列的基本概念和原理
    • 2.1、消息的生产者和消费者
    • 2.2、Broker
    • 2.3、点对点消息队列模型 ----- 线程池
    • 2.4、发布订阅消息模型
    • 2.5、消息的顺序性保证
    • 2.6、消息的ACK确认机制
    • 2.7、消息的持久化
    • 2.8、消息的同步和异步收发
    • 2.9、消费组的概念
  • 三、消息队列产品
  • 后言

一、使用消息队列的场景

  1. 异步处理。
  2. 流量控制。
  3. 服务解耦。
  4. 发布订阅。
  5. 高并发缓冲。

1.1、消息队列的异步处理

主要应用于短信通知、终端状态推送、App推送、用户注册等。

同步处理:

APP
网关
风控
库存
订单
短信
统计

异步处理:

生产
消费
消费
消费
APP
网关
风控
库存
消息队列
订单
短信
统计

异步处理的优势:更快速返回结果;减少等待,实现并发处理,提升系统总体性能。

消息队列的模式可以有:
(1)1对1:读取之后立刻从队列中移除消息。
(2)1对多:这种模型是发布订阅模型,消息队列的元素可以被重复消费。至于何时删除消息,可以设置消息的存活周期;比如kafka可以设置24H后删除消息。

1.2、消息队列的流量控制(削峰)

在秒杀场景下的下单状态,使用消息队列隔离网关和后端服务,以达到流量控制和保护后端服务的目的。

生产
消费
APP
网关
消息队列
秒杀服务

设置消息队列的最大限制数量,在达到最大数量时网关不再生成消息到消息队列中。

可以这么想:有一个商品秒杀活动,商品数量为100,当消息队列的数量达到100时不再生产秒杀成功消息,直接返回秒杀失败给用户,只有1到100的用户秒杀成功 获得商品。

1.3、消息队列的服务解耦

A系统负责数据分发,其他系统调用A系统提供的接口处理数据;当新增一个系统时,A系统需要改代码调用新的系统,并实现新的接口给新的系统去调用。这种方式是系统间高度耦合。

调用接口
调用接口
调用接口
调用接口
A系统
B系统
C系统
D系统
E系统(新增)

使用消息队列,A系统负责将数据分发到MQ,消费端根据需要从MQ获取消息即可,不需要就取消MQ的消费。

消费
消费
消费
消费
A系统
消息队列
B系统
C系统
D系统
E系统(新增)

1.4、消息队列的发布订阅

用户需要先去注册,才能收到相关消息。

消费
消费
消费
订阅
系统
消息队列
B系统
C系统
D系统
E系统(新增)

比如游戏里面跨服:
(1) 广播今天整体还剩多少把屠龙刀可以暴。
(2) 广播用户暴的屠龙刀的消息。

1.5、消息队列的高并发缓冲

这个和消息队列的流量控制(削峰)有些类似。区别在于,这里没有大小限流,可能在某个时间点会出现超过后端处理能力的访问;比如后端处理能力是50000每秒,在某个时间点出现每秒80000的访问,这就可能造成击穿。

针对此情况,消息全部放入消息队列,消息队列提供可以把数据固化到磁盘的能力,降低高峰数据对后端的短暂冲击。

生产
消费
短暂高峰时缓存
短暂高峰退去后恢复
APP
网关
消息队列
后端服务
磁盘

比如,后端处理能力50000,某个短暂时间点(比如一秒的时间)数据访问达到80000,消息队列将多的数据缓存到磁盘,后端仍然处理50000数据;冲击点退去后,访问数据降到了30000,那么消息队列将把缓存的数据放到后端处理。

比如kafka 日志服务、监控上报。

二、消息队列的基本概念和原理

消息队列全称MessageQueue,简称MQ。本质是一个队列,FIFO先进先出,只不过队列中存放的内容是message,从而称为消息队列(消息+队列)。

主要用途:不同服务server、进程process、线程thread之间通信。

2.1、消息的生产者和消费者

消息生产者Producer:发送消息到消息队列。
消息消费者Consumer:从消息队列接收消息。
被动接受消息 s->c。
主动拉取消息 s<- c pull。

通常,是由消费者Consumer去拉取消息,避免采用推送的方式。因为服务端不知道消费者的处理能力,可能会造成数据丢失。

2.2、Broker

Broker的概念来自与Apache ActiveMQ,通俗的讲就是MQ的服务器。一般来说,一个服务器机器只有一个Broker,不要出现多个Broker。

如果有多个Broker,可以采用集群的方式。

生产
消费
Producer
Broker
Consumer

2.3、点对点消息队列模型 ----- 线程池

消息生产者向一个特定的队列发送消息,消息消费者从该队列中接收消息。
一条消息只有一个消费者能收到。
消息队列的概念和原理_第1张图片

发送消息
消费
确认
client 1
消息队列
client 2

2.4、发布订阅消息模型

实际操作过程中,发布订阅消息模型中,支持向一个特定的主题Topic发布消息,0个或多个订阅者接收来自这个消息主题的消息。在这种模型下,发布者和订阅者彼此不知道对方。
消息队列的概念和原理_第2张图片

2.5、消息的顺序性保证

基于Queue消息模型,利用FIFO先进先出的特性,可以保证消息的顺序性。

2.6、消息的ACK确认机制

即消息的Ackownledge确认机制,为了保证消息不丢失,消息队列提供了消息Acknowledge机制,即ACK机制,当Consumer确认消息已经被消费处理,发送一个ACK给消息队列,此时消息队列便可以删除这个消息了。
如果Consumer宕机/关闭,没有发送ACK,消息队列将认为这个消息没有被处理,会将这个消息重新发送给其他的Consumer重新消费处理。

通过牺牲吞吐量获得实时性。

2.7、消息的持久化

消息的持久化,对于一些关键的核心业务来说是非常重要的,启用消息持久化后,消息队列宕机重启后,消息可以从持久化存储恢复,消息不丢失,可以继续消费处理。

对于生产者,将数据发送到消息队列,消息队列会保存多个副本,即使MQ服务器奔溃,重启仍能找到生产者的消息数据。
对于消费者,拉取到消息后,将返回一个信息给MQ告诉它已经获得了消息,MQ将保存相关数据,即使MQ服务器奔溃,重启仍能知道消费者已经获取了哪些数据,避免重复发送。

2.8、消息的同步和异步收发

同步: 消息的收发支持同步收发的方式 一应一答。
同时还有另一种同步方式:同步收发场景下,消息生产者和消费者双向应答模式。
消息的接收如果以同步的方式(Pull)进行接收,如果队列中为空,此时接收将处于同步阻塞状态,会一直等待,直到消息的到达。

异步: 消息的收发同样支持异步方式:异步发送消息,不需要等待消息队列的接收确认;异步接收消息,以Push的方式触发消息消费者接收消息。

2.9、消费组的概念

类似线程池;如果消费者的处理能力较低时,可以使用消费组来处理,一个消费组里面包含多个消费者。

发送消息
消费
消费组
消费者 1
消费者 2
消费者 ...
消费者 n
生产者
消息队列

比如,MQ推送数据的能力是10w每秒,而消费者的处理能力是1w每秒,那么就可以使用一个消费组包含10个消费者来处理消息。这时消费者使用的是点对点消息队列模型 。

三、消息队列产品

特性 RabbitMQ RocketMQ Kafka ZeroMQ
单机吞吐量 万级,比 RocketMQ、Kafka 低一个数量级 10 万级,支撑高吞吐 10 万级,高吞吐,一般配合大数据类的系统来进行实时数据计算、日志采集等场景 100万级别,最早设计用于股票实时交易系统
topic 数量对吞吐量的影响 topic 可以达到几百/几千的级别,吞吐量会有较小幅度的下降,这是 RocketMQ 的一大优势,在同等机器下,可以支撑大量的 topic topic 从几十到几百个时候,吞吐量会大幅度下降,在同等机器下,Kafka 尽量保证 topic 数量不要过多,如果要支撑大规模的 topic,需要增加更多的机器资源
时效性 微秒级,这是RabbitMQ 的一大特点,延迟最低 ms 级 延迟在 ms 级以内 延迟在微妙级别/毫秒级
可用性 高,基于主从架构实现高可用 非常高,分布式架构 非常高,分布式,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用 不是一个独立的服务,要嵌套到自己的程序里面去
消息可靠性 基本不丢 经过参数优化配置,可以做到 0 丢失 同 RocketMQ
功能支持 基于 erlang 开发,并发能力很强,性能极好,延时很低 MQ 功能较为完善,支持分布式部署,扩展性好 功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用 如果需求是将消息队列的功能集成到系统进程中,可以考虑使用

后言

本专栏知识点是通过<零声教育>的系统学习,进行梳理总结写下文章,对c/c++linux系统提升感兴趣的读者,可以点击链接,详细查看详细的服务:C/C++服务器课程

你可能感兴趣的:(#,Kafka,大数据,kafka,中间件,后端,分布式)