【Kafka】消息队列学习(一):为什么需要Kafka?从消息队列到整体架构

一、为什么需要Kafka这样的消息队列

在没有消息队列之前,两个系统之间最直接的通信方式通常就是:

复制代码
系统A
  ↓
直接调用
  ↓
系统B

例如一个电商系统中,用户提交订单以后,需要执行:

复制代码
创建订单
   ↓
扣减库存
   ↓
发送短信
   ↓
发送邮件
   ↓
记录日志

最直接的写法可能类似:

复制代码
createOrder();       // 创建订单
reduceStock();       // 扣减库存
sendMessage();       // 发送短信
sendEmail();         // 发送邮件
writeLog();          // 写入日志

这样写功能当然可以实现,但会出现一个比较明显的问题:

复制代码
这些操作全部串在一起了

假设:

复制代码
sendMessage();

执行比较慢,那么整个下单流程也会被拖慢。

甚至如果短信服务出现故障:

复制代码
订单系统
   ↓
调用短信系统
   ↓
短信系统异常
   ↓
订单流程可能受到影响

也就是说,两个系统之间:

复制代码
耦合得比较紧

如果中间增加一个消息队列:

复制代码
订单系统
    ↓
发送消息
    ↓
消息队列
   ↙   ↓   ↘
库存  短信  日志
系统  系统  系统

订单系统只需要完成:

复制代码
我产生了一条"订单创建成功"的消息

然后把消息交给消息队列。

至于谁去处理:

复制代码
库存系统
短信系统
日志系统

订单系统并不需要关心。

这就是消息队列非常重要的一个作用:

复制代码
系统解耦

除了系统解耦之外,消息队列还有另外两个非常常见的作用:

复制代码
异步处理
+
流量削峰

例如某一秒突然出现:

复制代码
100000个请求

如果后面的业务系统每秒只能处理:

复制代码
10000个请求

直接把这 10 万个请求全部打过去:

复制代码
10万请求
    ↓
业务服务器
    ↓
瞬间压力过大

就可能导致系统崩溃。

加入消息队列之后:

复制代码
10万请求
    ↓
消息队列
    ↓
暂时保存
    ↓
消费者按照自己的速度处理

这样消息队列就像一个:

复制代码
缓冲区

把突然出现的大量流量先接住,然后慢慢处理。

所以从应用角度来说,Kafka 首先可以理解成:

一个负责在不同系统之间暂存和传递消息的平台。

二、Kafka到底是什么

Kafka 最开始可能很容易被理解成:

复制代码
一个队列

但实际上 Kafka 并不只是一个简单的队列。

更准确地说,Kafka 是一个:

复制代码
分布式事件流平台

不过对于刚开始学习来说,不需要先纠结这个定义。

先把 Kafka 理解成:

复制代码
生产者
   ↓
Kafka
   ↓
消费者

就够了。

这里有三个最重要的角色:

复制代码
Producer
Kafka Broker
Consumer

分别对应:

复制代码
Producer:生产消息

Broker:保存和管理消息

Consumer:消费消息

例如:

复制代码
订单系统

产生一条订单信息:

复制代码
{
    "orderId": 10001,
    "userId": 9527,
    "price": 299
}

订单系统就是:

复制代码
Producer

它把消息发送给 Kafka:

复制代码
Producer
   ↓
Kafka

Kafka 负责把消息保存下来。

库存系统再从 Kafka 中读取:

复制代码
Kafka
   ↓
Consumer

那么库存系统就是:

复制代码
Consumer

整个过程就是:

复制代码
Producer
   ↓
发送消息
   ↓
Kafka
   ↓
保存消息
   ↓
Consumer
   ↓
消费消息

所以第一阶段学习 Kafka 时,可以先牢牢记住:

复制代码
Kafka并不是主动帮我们处理业务

Kafka 做的主要事情是:

复制代码
接收消息
保存消息
提供消息

真正处理业务的还是:

复制代码
Producer
和
Consumer

三、Producer、Broker、Topic和Consumer是什么

Kafka 中有几个最基础的概念:

复制代码
Producer
Broker
Topic
Consumer

先来看 Producer。

1. Producer

Producer 就是:

复制代码
消息生产者

例如:

复制代码
订单系统
日志系统
支付系统
设备采集系统

都可能成为 Producer。

Producer 的工作非常简单:

复制代码
创建消息
   ↓
发送给Kafka

例如:

复制代码
Producer
   ↓
"订单10001创建成功"
   ↓
Kafka

2. Broker

Kafka 真正运行起来以后,本质上也是一个:

复制代码
服务程序

运行 Kafka 服务的服务器节点通常叫:

复制代码
Broker

例如:

复制代码
服务器1 → Broker 1
服务器2 → Broker 2
服务器3 → Broker 3

多台 Broker 可以组成:

复制代码
Kafka Cluster
Kafka集群

结构可以简单理解成:

复制代码
             Kafka Cluster

       ┌────────┬────────┐
       ↓        ↓        ↓

    Broker1  Broker2  Broker3

为什么需要多个 Broker?

因为一台机器会存在:

复制代码
性能上限
磁盘上限
故障风险

多台机器以后,可以共同:

复制代码
存储数据
处理请求
提供容错

这也是 Kafka 被称为:

复制代码
分布式系统

的重要原因之一。


3. Topic

Producer 把消息发送给 Kafka 时,不能随便乱放。

需要告诉 Kafka:

复制代码
这是什么类型的消息

于是就有了:

复制代码
Topic

Topic 可以理解成:

复制代码
消息的分类

例如:

复制代码
order_topic       → 订单消息

payment_topic     → 支付消息

log_topic         → 日志消息

订单系统发送消息:

复制代码
订单系统
   ↓
order_topic

支付系统发送消息:

复制代码
支付系统
   ↓
payment_topic

所以 Topic 可以先简单理解成:

Kafka 中用于对不同类型消息进行分类的逻辑容器。


4. Consumer

Consumer 就是:

复制代码
消息消费者

负责从 Kafka 中取出消息。

例如:

复制代码
Kafka
   ↓
订单消息
   ↓
库存系统

库存系统读取订单消息并完成扣库存,它就是一个 Consumer。

因此 Kafka 最基础的整体结构就是:

复制代码
                 Producer
                     ↓
                  发送消息
                     ↓
                  Topic
                     ↓
                 Kafka
                     ↓
                  保存消息
                     ↓
                 Consumer
                     ↓
                  处理消息

理解这几个角色以后,Kafka 的整体框架基本就已经出来了。

四、一条Kafka消息到底是怎么流转的

现在把整个过程真正串起来。

假设有一个订单系统:

复制代码
Order Service

用户成功创建订单以后产生一条消息:

复制代码
{
    "orderId": 10001,
    "price": 299
}

Producer 将消息发送给:

复制代码
order_topic

流程:

复制代码
订单系统
   ↓
Producer
   ↓
order_topic
   ↓
Kafka Broker

Kafka 收到以后负责保存。

然后库存系统:

复制代码
Stock Service

作为 Consumer:

复制代码
Kafka
   ↓
读取order_topic
   ↓
Stock Consumer
   ↓
扣减库存

整个完整流程就是:

复制代码
                 用户创建订单
                      ↓
                  订单系统
                      ↓
                   Producer
                      ↓
              发送订单消息
                      ↓
                order_topic
                      ↓
                 Kafka Broker
                      ↓
                  保存消息
                      ↓
                   Consumer
                      ↓
                  库存系统
                      ↓
                  扣减库存

这样订单系统就不用直接写:

复制代码
reduceStock();

而是:

复制代码
只发送一个订单创建消息

库存系统自己去消费。

假设以后还要增加:

复制代码
短信系统
积分系统
日志系统

原来的订单系统也不需要不断增加:

复制代码
sendMessage();
addPoints();
writeLog();

而是可以变成:

复制代码
                        Kafka
                          ↓

        ┌─────────────────┼─────────────────┐
        ↓                 ↓                 ↓

     库存系统           短信系统           积分系统

这就是前面提到的:

复制代码
解耦

Producer 不需要知道:

复制代码
到底有几个Consumer
Consumer具体怎么处理

它只负责:

复制代码
把消息送到Kafka

五、先跑一个最简单的Kafka消息流程

Kafka 环境搭建后,可以直接通过 Kafka 自带的命令测试 Producer 和 Consumer。

假设已经存在一个:

复制代码
test

Topic。

可以先启动一个消费者:

复制代码
kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test

其中:

复制代码
--bootstrap-server localhost:9092

表示连接:

复制代码
localhost:9092

这个 Kafka Broker。

而:

复制代码
--topic test

表示消费:

复制代码
test

这个 Topic 中的消息。

然后再启动一个 Producer:

复制代码
kafka-console-producer.sh --bootstrap-server localhost:9092 --topic test

启动以后输入:

复制代码
hello kafka

Producer 会把:

复制代码
hello kafka

发送给 Kafka。

整个流程:

复制代码
Producer终端
      ↓
hello kafka
      ↓
test Topic
      ↓
Kafka Broker
      ↓
Consumer终端
      ↓
hello kafka

于是 Consumer 就能够读取到:

复制代码
hello kafka

这里看起来只是:

复制代码
发送一句话

但实际上已经把 Kafka 最基本的工作模型完整跑了一遍:

复制代码
Producer
   ↓
Topic
   ↓
Broker
   ↓
Consumer

因此第一阶段学习 Kafka,并不需要一开始就记:

复制代码
ISR
Replica
KRaft
Leader
Follower
Controller
Rebalance

这些概念。

先把最基础的一层搞清楚:

复制代码
                Kafka

Producer  →  Broker  →  Consumer
              ↑
            Topic

其中:

复制代码
Producer
负责生产消息

Topic
负责对消息分类

Broker
负责接收和保存消息

Consumer
负责读取和处理消息

而 Kafka 最常见的三个价值可以先记成:

复制代码
系统解耦
+
异步处理
+
流量削峰

不过这里还留下了一个非常重要的问题。

前面一直说:

复制代码
消息保存在Topic里面

但实际上:

Topic 本身只是一个逻辑概念,Kafka 中真正负责存储消息的是 Partition。

也就是说,一个 Topic 内部实际上可能是:

复制代码
Topic:order_topic

├── Partition 0
├── Partition 1
└── Partition 2

Producer 发送过来的消息最终会进入某一个:

复制代码
Partition

而 Kafka 为什么一定要设计 Partition、一个 Topic 为什么要拆成多个 Partition、Offset 又是什么,这些就是理解 Kafka 真正存储模型的关键。

下一篇继续从:

复制代码
Topic
   ↓
Partition
   ↓
Offset

这一条线开始分析 Kafka 中一条消息到底保存在哪里。

0voice · GitHub

相关推荐
clz13145211 小时前
风险特征系统 EPC 子系统:基于 Kafka 数据源与数据集配置的 Flink 指标清洗加工
分布式·flink·kafka
AI_Auto1 小时前
架构视角看数字化转型|完整复盘:架构先行,完成数字化组织与运营重构
网络·重构·架构
富士康质检员张全蛋2 小时前
Kafka实战 生产阶段 消费阶段的拦截器
kafka
传奇开心果编程2 小时前
【Rust入门知识点学与练】第26课:Unsafe Rust
开发语言·学习·rust
晚安日记wanna2 小时前
政务 Agent 面试真题五个得分点缺一就掉档
面试·架构
励志不掉头发的内向程序员2 小时前
【LibreCAD 2D架构】从 addHistory 到 RS_UndoCycle:LibreCAD 里的两套 History 与撤销机制
开发语言·c++·qt·学习·系统架构
`流年づ2 小时前
人工智能学习笔记 - 自动微分
人工智能·笔记·学习
Quor2 小时前
Zorv AI GenUI 技术架构深度解析:从双面设计到安全边界
人工智能·ui·架构
晚安日记wanna2 小时前
分布式和微服务差在哪从一次订单超时雪崩说起
面试·架构