💯 作者: 俗世游子。 2014年入行的程序猿。多年开发和架构经验。专注于Java、云原生、大数据等技术。从CRUD入行,负责过亿级流量架构的设计和落地,解决了千万级数据治理问题。
💥 微信公众号:「谢先生说技术」关注同头像哦~

📖 同名社区:​​51CTO​​​、 ​​github​​​、掘金​、​​gitee​​​。

📂 清单: ​​​goku-framework​​​、​【更新中】享阅读II

分布式流处理组件-理论实战结合篇:Kafka架构理论_kafka

前言

前面我们已经介绍了关于Kafka相关介绍和基本安装,相信大家已经通过验证脚本已经做了最基础的验证。

当然了,肯定也有很多人觉得不爽:我刚要开始在Kafka上大展拳脚,你就结束了。就这???而且还要浪费我启动Kafka的时间。

分布式流处理组件-理论实战结合篇:Kafka架构理论_kafka_02

别急,这不是最新的教程就来了么,本次我一定要让你们嗨起来

快速启动Kafka

首先,我们需要了解到。​​ssh​​除了能够通过xshell等工具连接到指定的服务器之外,我们还可以直接将操作命令发送到指定的机器进行执行,例如:

ssh localhost "ls"

分布式流处理组件-理论实战结合篇:Kafka架构理论_kafka_03

操作没有任何问题。不过需要注意我在图中框柱的部分:需要输入密码

你都要在我的机器上执行命令了,我让你输个密码,不过分吧

分布式流处理组件-理论实战结合篇:Kafka架构理论_kafka_04

免密登录

那既然过分,我们就来一个不需要免密登录的方式。别急,我教你啊

免密登录的核心在于​​.ssh​​目录,这东西我们无法自动生成,必须借助某种手段

ssh localhost

随后我们需要通过​​exit​​退出来,这样我们才会回到自己的主战场上

​.ssh​​是一个隐藏文件,必须通过​​ls -la​​才能查看到,或者直接通过​​cd .ssh​​进入到文件夹内部

这个文件不建议手动创建,当前目录和内部文件对权限要求其为苛刻

分布式流处理组件-理论实战结合篇:Kafka架构理论_kafka_05

接下来我们需要生成公私钥,我们一切默认即可

ssh-keygen

分布式流处理组件-理论实战结合篇:Kafka架构理论_kafka_06

最后,通过​​ssh-copy-id​​命令将​​id_rsa.pub​​发送到指定的机器上,就能完成免密登录了

ssh-copy-id -i id_rsa.pub localhost

当出现​​authorized_keys​​的文件,说明整个过程已经成功,随即通过​​ssh localhost​​进行尝试,不需要输入密码即为成功

分布式流处理组件-理论实战结合篇:Kafka架构理论_kafka_07

到此免密登录的过程就已经全部结束,接下来我们通过shell脚本来处理多台机器启动/停止Kafka的问题

快速启动多台Kafka

如果大家了解​​ansible​​,直接跳过本节,继续往下看

该脚本必须放到​​/usr/local/bin​​下, 并且需要授予可执行权限

这里必须要用完整的全路径:在ssh下执行不会去找环境变量

#!/bin/bash

case $1 in
"start")
for i in node01 node02 node03
do
ssh $i "/usr/local/opt/kafka-3.3.1/kafka-server-start.sh -daemon /usr/local/opt/kafka-3.3.1/config/server.properties"
done
;;
"stop")
for i in node01 node02 node03
do
ssh $i "/usr/local/opt/kafka-3.3.1/kafka-server-stop.sh"
done
;;
esac

随后通过​​chmod a+x​​授权可执行,然后这样就能开始快乐的启动kafka集群了。

关于ZK的集群,甚至是更多的其他的,都可以按照这种方式来处理,是不是非常方便

以上内容纯属锦上添花,下面我们进入本文正题~

Kafka基础架构

分布式流处理组件-理论实战结合篇:Kafka架构理论_kafka_08

在详述Kafka架构之前,这里先来一个重要的说明:

  • Kafka在2.8.0之后可以采用KRaft模式来摆脱整体架构对Zookeeper的依赖

接下来我们来一一介绍Kafka架构中非常重要的角色信息

架构角色

Producer

字如其名。负责生产消息,主要由业务系统负责。消息生产者会将业务应用产生的消息发送到Broker集群中。

Kafka为我们提供了多种发送方式:

  • 同步发送
  • 异步发送
  • 单向发送
  • ...

同时为了方便各业务系统和Kafka间的使用。Kafka为我们提供了非常完善的对接方案,包括但不限定于:

  • 各种开发语言
  • 大数据组件
  • ...

后面我们会从最基础的​​kafak-console-producer.sh​​来了解

Consumer

Kafka不负责处理消息,它只是消息的搬运工。而负责消费消息的程序属于消费者。消费者会从Broker拉取消息,然后开始对消息进行消费处理。

一般情况下消息的消费形式分为:拉取式消费、推送式消费

Kafka通过主动拉取的方式进行消费,防止消费端消费不及时造成消费端消息积压。

Kafka的消费者消费消息已Topic为基本单元:

  • 不同的消费者可以消费同一个Topic内的消息,互不影响

当消费者配置​​group.id​​相同,可将其看做为一组消费者,称为消费者组

  • 而同一组消费者下的消费者对同一个Topic内的消息进行消费时只能由其中之一消费

同样我们会从最基础的​​kafak-console-consumer.sh​​来了解

Broker

指代的是服务器代理节点。我们启动的kafka server进程都可以看做是一个Broker实例。一个Kafka集群由多个broker实例搭建而成,而配置​​broker.id​​就是为了保证集群内的broker标识唯一

第一节我们由三个实例组成了kafka集群

Broker内部采用Topic来区分存储消息。在一个Broker中可以存在多个Topic。需要注意的是:

  • Topic是一个逻辑概念

Topic可以将自己分为一个或者多个分区【partition】,partition属于物理层面。每个partition下存放不同的数据文件。同时我们可以设置partition的副本数,用来保证数据的安全性。

在下一节中我们可以看到详细的信息

leader处理数据存放,其他的只能去leader中进行数据同步。而涉及到主从间的数据同步,kafka为了引入了ISR、OSR、AR机制确定需要同步数据的实例,同时通过HW、LEO来确定需要同步数据的位置

集群内的实例关系一般为主从主备。在Kafka集群中采用主从模式。Producer和Consumer只能与Leader交互,Follower不接受任意请求。

Broker章节我们详细介绍

QA: 为什么推出KRaft模式

我们都知道,Zookeeper的定位是一个分布式协调框架,而ZK在整个Kafka的架构中也起到了非常重要的协调作用。

以下是整个Kafka在ZK中存储的数据信息,后面在Broker的内容中我会专门介绍

分布式流处理组件-理论实战结合篇:Kafka架构理论_kafka_09

ZK存在的地位

注册中心

当Kafka启动时,会将部分元数据信息存储到ZK中,往下看:

Broker

Broker既然为分布式集群架构,那么必然是需要通过ZK来管理实例的,在ZK下有专门的空间来存储相关的Broker列表信息

  • ​/xx/brokers/ids​

在Broker启动后,会将对应的​​broker.id​​注册到ids下,例如​​/kafka/brokers/ids/1​​,并且存放对应的IP和端口等信息

分布式流处理组件-理论实战结合篇:Kafka架构理论_kafka_10

当然,该节点下的实例节点属于临时节点,当broker停止之后就会从ids下删除掉

topic

ZK下也对topic进行统一管理,其中已​​/xx/brokers/topics/{topicName}​​为节点进行存储。并且topic可以分为不同的partition,那么partition和broker间的对应关系也是需要记录的

同时,partition间的主从切换也需要通过ZK的协作,在​​/xx/brokers/topics/{topicName}/partitions/{index}/state​​下能够看到对应的数据处理

consumer

在​​/xx/consumers/{group_id}​​下记录消费者的三类数据

  • 消费组下的消费者的实例集合
  • 消费组要消费的topic
  • 记录每个分区下的offset偏移

同时为了降低对ZK的依赖,减少和ZK间的交互。offset由kafka自身维护在​​__consumer_offsets​​的topic下

Controller选举

事实上为了有效防止数据统一和网络等问题,并不是所有的Broker都需要跟ZK进行交互。在Kafka集群启动之后会选举出一个管理单元,我们将其称之为Controller

而多个Broker想要升级为唯一的Controller,就必须要借助ZK才能实现

  • ​/xx/controller​​为临时节点,记录着幸运儿Broker的相关信息。同时其他的Broker会监听着当前节点,随时准备上位

同样的,关于Controller更多其他的功能,我们在Broker章节详细介绍

ZK存在对Kafka的弊端

从以上的结论分析来看,ZooKeeper在Kafka的架构中起到了决定性的作用。那么首先从维护方面谈起

  • 在维护Kafka的同时还需要额外对Zookeeper的维护,加大了维护成本
  • 并且分布式组件依赖另一个分布式系统,无疑会加重整体架构的复杂度

其次:Controller选举依赖于Zookeeper:

  • Kafka依赖于单个Controller与ZK进行交互,而如果该Controller出现宕机等情况,就需要从其他Broker中选举中新的Controller
  • 在选举新Controller和Broker间同步数据的过程在分区数较多的情况下是非常耗时的,而且此时整个Kafka集群是无法正常工作的

当Broker分区数变多时,Zookeeper存储的元数据不断增加,此时还会导致ZK集群的压力过大。

  • 当ZK存储数据到达一定级别之后,监听延迟增加。影响Kafka的集群工作

基于上述弊端,需要对Kafka的结构进行升级,据官方介绍:升级后的架构可轻松支撑百万分区

所以说,如果业务规模庞大的话,推荐对Kafka进行升级

架构介绍

这是一个非常重要的设计原则

在互联网时代下,各类高并发系统层出不穷,项目规模也在逐步扩大。在此背景下传统的单体项目已无法满足此需求。我们就需要【分布式系统】来提供更强、更好的服务,为了能够针对系统设计出更好的架构,往往需要分析系统架构,考虑如何对系统进行划分。

此时我们需要一套系统的方法论来做上面的事情。这就是本次我要引出非常重要的AKF原则

这里不会考虑CAP定律和Base理论
AKF本身都可以介绍一个章节,我们已Kafka为主,就不介绍那么细致。

AKF将分布式系统从三个维度上进行拆解,分别为

  • X轴:水平扩展
  • Y轴:按功能拆分
  • Z轴:分区
基于X轴的水平扩展

X轴从克隆服务、数据开始,将它们部署到不同的服务器上,并通过负载均衡的方式进行调用。以此来解决服务的可用性。

分布式流处理组件-理论实战结合篇:Kafka架构理论_kafka_11

这种方式的操作成本是最低的。但是对于空间利用率不高。

基于Y轴的业务拆分

Y轴从业务功能上对整个分布式系统进行细粒度的拆分,使得各组件职责、功能更加明确。同时也能够保证对其他业务不受影响,配合X轴的水平扩展,从而能够提高了整个系统的性能

分布式流处理组件-理论实战结合篇:Kafka架构理论_kafka_12

基于Z轴分区处理

Z轴更多关注的是服务和数据的优先级划分,比如按照地域、客户定制等

分布式流处理组件-理论实战结合篇:Kafka架构理论_kafka_13

而从数据方面讲,数据库分表就属于是Z轴的思想:

  • 当单表无法承载大量数据的写入,那么通过某一个维度将单表分为多表记录

从AKF原则看Kafka架构

分布式流处理组件-理论实战结合篇:Kafka架构理论_kafka_14

Kafka服务节点Broker本身支持多台节点部署,方便处理单点故障问题且能够在解决数据存储问题。

将生产者很大的数据已某种规律分散在不同的Broker节点上。这是在大数据场景下非常重要的分治思想

如架构图所示:

  • AKF中,Topic的存在可以套在Y轴上,将不同业务场景的数据分别通过不同的Topic进行生产。例如
  • 订单
  • 支付
  • ...
  • 而为了方便扩展和提高Kafka的吞吐量,一个Topic可以分为多个分区Partition。分区分散在不同的Broker节点上。而本身Topic内的数据也会通过策略分散存储在不同的Partition中。这就是Z轴
  • 消费者根据这一设计,也提出了消费者组的概念。组内每个消费者成员都可以通过指定消费不同的分区数据来达到并行消费的能力,且组与组之间的消费者互不干扰
  • 并且为了提高可用性和数据的安全性,Kafka为每个Partition增加了若干分散在不同Broker上的副本Partition,按照主从模式进行管理。
  • 生产者和消费者只能对Leader生产或消费数据,副本数据会从Leader进行同步。
  • 当Leader挂掉后,Follower会提升为Leader角色。
  • Zookeeper中记录相对应的Leader信息,而在2.8.0之后,Kafka推出的KRaft模式将改变这一方式。

下期预告

本篇内容过于理论,后面我们开始实际动手进行操作,期待~~~