Kafka 总结学习
Kafka Need No Keeper
最近在鹅厂工作中不断接触到Kafka,虽然以前也使用过,但是对其架构和发展过程总是模模糊糊,所以在回学校准备末考的时候找些资料总结一下。
Kafka Need No Keeper 是一个在Kafka Submit分享的标题,我也是看了Kafka needs no Keeper(关于KIP-500的讨论)这篇博客分享后才对Kafka有了初期的认识,如果想要了解细节的话可以直接阅读该博客分享,本篇博客是一次对Kafka的自我总结,多少有些大白话和概括之意。
Kafka架构
Kafka是什么?Apache Kafka 是一款分布式流处理框架(新版本后,定位发生了改变),用于实时构建流处理应用。
Kafka的架构可以简单分为Client和Broker两部分。在Kafka发展过程中,Kafka都是不断减少这两部分对Zookeeper的依赖。
那为什么要减少对Zookeeper的依赖呢?
- Kafka在新版本后定位变成了分布式流处理框架,但是本质上还是一个消息中间件,中间件与中间件之间不应该存在依赖关系,需要降低耦合。
- Kafka与Zookeeper不断通信,不断写入数据,而Zookeeper一致性要求较高,当某个数据节点信息发生变更时,会通知其他节点同步更新,半数以上完成更新才能返回,写入性能较差,影响了Kafka的性能。
Client架构
Client一般分为三类,Consumer Client、Producer Client和Admin Tool。
旧版架构
- Producer Client 只需要向Kafka集群中发送消息,不需要连接Zookeeper
- Consumer Client 需要读取某主题某分区内的消息,那么需要知道读取哪条消息(读取offset)和下一次读哪条消息(提交offset),所以需要和Zookeeper交互(offset保存在ZK中)
- Admin Tool 执行主题的操作,因为元数据保存在ZK中,所以需要与ZK交互

可以看出,Zookeeper在Kafka中①存储元数据
新版架构
新版主要针对旧版中的Consumer Client和Admin Tool改进
- Offset改进:在Kafka中新建一个内部主题_consumer_offset用来保存消费者组的offset,提交和获取offset都可以直接与Kafka集群交互获取。
- Rebalance改进:在旧版架构中,消费者组中的消费者消费的主题分区信息都是保存在ZK中,在新版架构改进中,每一个消费组使用一个Coordinator来控制重分区过程。
- Admin改进:社区引入了新的运维工具AdminClient以及相应的CreateTopics、DeleteTopics、AlterConfigs等RPC协议,替换了原先的Admin Tool,这样创建和删除主题这样的运维操作也完全移动Kafka这一端来做。

| Question | Answer |
|---|---|
| 重分区是什么? | 如上图,重分区就是将消费者组里订阅主题下的分区重新分配给当前组内消费者实例的过程。 |
| 重分区发生条件是什么? | ①消费者组消费者数量改变; ②订阅的主题数量改变; ③订阅的主题下分区数量改变。 |
| 怎么进行重分区? | 真正的重分区是有Group Leader来完成的。 第一个进入Consumer Group的消费者实例为leader,它向Coordinator申请消费者组成员列表,然后按照分区策略进行分区,接着将分区的结果告诉Coordinator,最后由Coordinator告知所有的消费者分区信息。 |
| Coordinator是怎么找到的 | 消费者组向任意一个Broker发送groupCoordinatorRequest请求,集群返回一个负载最小的Broker节点使其成为当前消费者组的Coordinator。 |
| 分区策略是什么? | ①Range分区(默认):分块分区,对于每一个主题而言, 首先将分区按数字顺序排行序,消费者按名称的字典序排序,然后用分区总数除以消费者总数。如果能够除尽,平均分配;若除不尽,则位于排序前面的消费者将多负责一个分区。 ②RoundRobin分区:轮询分区,对所有主题而言,首先将所有主题的分区组成列表,然后按照列表重新轮询分配分区给不同的消费者。 |
Broker架构
现阶段架构
在现阶段结构中,Broker端是严重依赖Zookeeper的,基本上所有元数据信息和管理都要通过Zookeeper集群,如下图:

可以看出,Zookeeper在Kafka中有②集群管理和③选举Controller的作用
发展中的架构
第一步首先是隔离非Controller端对ZK的依赖;
第二步是移除Controller端对ZK的依赖,这一步可以采用基于Raft的共识算法来做(?)。

Kafka同步副本管理
基本概念
| 概念 | 简介 |
|---|---|
| LEO | Log End Offset。日志末端位移值或末端偏移量,表示日志下一条待插入消息的 位移值。 |
| LSO | Log Stable Offset。这是 Kafka 事务的概念。如果你没有使用到事务,那么这个值无意义。该值控制了事务型消费 者能够看到的消息范围。它经常与 Log Start Offset,即日志起始位移值相混淆,因为 有些人将后者缩写成 LSO,这是不对的。在 Kafka 中,LSO就是指代 Log Stable Offset。 |
| HW | 高水位值(High watermark)。这是控制消费者可读取消息范围的重要字段。一 个普通消费者只能“看到”Leader 副本上介于 Log Start Offset 和 HW(不含)之间的 所有消息。水位以上的消息是对消费者不可见的。 |
| AR | Assigned Replicas。AR 是主题被创建后,分区创建时被分配的副本集合,副本个数由副本因子决定。 |
| ISR | In-Sync Replicas。Kafka 中特别重要的概念,指代的是 AR 中那些与 Leader 保持同步的副本集合。在 AR 中的副本可能不在 ISR 中,但 Leader 副本天然就包含在 ISR 中。 |
Kafka文件大小对应关系:

ISR
Leader 与 Follower
ISR中的Leader是由Controller指定,与Leader保持同步用指标来衡量就是follower中LEO落后leader中LEO的时间不超过指定时间范围(replica.lag.time.max.ms=10s)。
(在旧版本中还有另外一个指标是落后的LEO条数,不过这样子的话每次发送大量数据后,一开始ISR就只有leader,到后面follower跟上的才能加入ISR,这样子会导致ZK的频繁写入修改性能下降)
另外在Leader挂掉后,Controller会让ISR中的一个Follower成为Leader,并且开始同步新的Leader的Offset。这里要注意的是有可能此时ISR中并没有Follower,所以有两种选择,①允许OSR的Follower成为Leader和②该分区没有Leader。这来源于设置unclean.leader.election.enable,设置为true为选择①,保证了系统的高可用性和损失了一致性,设置为false为选择②,保证系统的一致性和损失高可用性。
同时一个Leader和多个Follower看上是读写分离的结构,但是Kafka并不支持读写分离。原因由两点,①场景不合适,读写分离适用于读负载很大,而写操作不频繁的场景,显然Kafka不是;②同步机制,Follower和Leader之间存在不一致的窗口,很可能出现消息滞后(类似于幻读)
ACK机制
这主要决定了Producer发送信息时,Kafka的接受机制,有三种:
| ACK | 机制 |
|---|---|
| ack = 0 | at most once,最多一次语义,Producer不需要等待Broker回发确认消息,直接发送下一批消息。 |
| ack = 1 | at least onve,最少一次语义,Producer只要Leader成功消息并且返回确认后,就可以发送下一批消息 |
| ack = -1 | Producer需要等到Leader和ISR中的Follower同步完成并且返回确认后,才能发送下一批消息 |
那么问题就来,怎么实现Exactly Once呢?
Kafka Exactly Once 和事务机制
这里讨论的Exactly Once主要是针对Producer端,至于消费者的Exactly Once可以在客户端上保留偏移量来实现(参见flink事务机制)。
单Session情况
先来讨论单Session的情况,在Kafka中给每个Producer都分配了一个内部的唯一的PID,每次Producer发送信息时,带有的主键是<PID ,Topic,Partition,SequenceNumber>,Leader端收到信息后对相同的<PID,Topic,Partition>的SequenceNumber进行比较,如果来的信息比Leader端的小,证明数据重复,丢弃该条信息;如果来的信息比Leader端的大1,插入该信息;吐过来的信息比Leader端的大超过1,证明发生了乱序丢弃该信息。
跨Session情况
简单理解
在单Session的情况如果存在PID都可以保证Exactly Once,那么要是在不同的Session中我能拿到相同的PID就可以了。所以引入了一个TID(自己定义的)并且绑定了事务一开始的PID,只要事务没有提交,那么每次都拿着这个TID去获取对应的PID就可以保证Exactly Once了。
具体做法
内部引入了一个Transaction Coordinator用于分配PID和管理事务,并且在内置了一个主题Transaction Log用于记录事务信息,事务的操作简图如下:

| 步骤 | 具体内容 |
|---|---|
| 1.请求/返回Transaction Coordinator | 由于Transaction Coordinator是分配PID和管理事务的核心,因此Producer要做的第一件事情就是通过向任意一个Broker发送FindCoordinator请求找到Transaction Coordinator的位置。 |
| 2.TID->PID | 找到Transaction Coordinator后,具有幂等特性的Producer必须发起InitPidRequest请求以获取PID。 |
| 3 Producer生产消息 | ①Producer拿到PID后向Kafka主题发送消息 ②Transaction Coordinator会将该<Transaction, Topic, Partition>存于Transaction Log内,并将其状态置为BEGIN |
| 4 事务完成 | ①将PREPARE_COMMIT或PREPARE_ABORT消息写入Transaction Log。 ②以Transaction Marker的形式将COMMIT或ABORT信息写入用户数据日志以及_consumer_log中。 ③最后将COMPLETE_COMMIT或COMPLETE_ABORT信息写入Transaction Log中。 |
与两阶段提交的区别
- Kafka事务机制中,PREPARE时即要指明是PREPARE_COMMIT还是PREPARE_ABORT,并且只须在Transaction Log中标记即可,无须其它组件参与。而两阶段提交的PREPARE需要发送给所有的分布式事务参与方,并且事务参与方需要尽可能准备好,并根据准备情况返回Prepared或Non-Prepared状态给事务管理器。
- Kafka事务中,一但发起PREPARE_COMMIT或PREPARE_ABORT,则确定该事务最终的结果应该是被COMMIT或ABORT。而分布式事务中,PREPARE后由各事务参与方返回状态,只有所有参与方均返回Prepared状态才会真正执行COMMIT,否则执行ROLLBACK
- Kafka事务机制中,某几个Partition在COMMIT或ABORT过程中变为不可用,只影响该Partition不影响其它Partition。两阶段提交中,若唯一收到COMMIT命令参与者Crash,其它事务参与方无法判断事务状态从而使得整个事务阻塞
- Kafka事务机制引入事务超时机制,有效避免了挂起的事务影响其它事务的问题
- Kafka事务机制中存在多个Transaction Coordinator实例,而分布式事务中只有一个事务管理器
人生此处,绝对乐观
Kafka 总结学习的更多相关文章
- kafka基本原理学习
下载安装地址:http://kafka.apache.org/downloads.html 原文链接:http://www.jasongj.com/2015/01/02/Kafka深度解析 Kafk ...
- Kafka入门学习(一)
====常用开源分布式消息系统 *集群:多台机器组成的系统叫集群. *ActiveMQ还是支持JMS的一种消息中间件. *阿里巴巴metaq,rocketmq都有kafka的影子. *kafka的动态 ...
- Kafka入门学习随记(二)
====Kafka消费者模型 参考博客:http://www.tuicool.com/articles/fI7J3m --分区消费模型 分区消费架构图 图中kafka集群有两台服务器(Server), ...
- Kafka入门学习--基础
Kafka是什么 Kafka是最初由Linkedin公司开发,是一个分布式.支持分区的(partition).多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就可 ...
- kafka初步学习
消息系统 什么是消息系统? 消息系统负责将数据从一个应用程序传输到另一个应用程序,因此应用程序可以专注于数据,但不担心如何共享它.分布式消息传递给予可靠消息队列的概念.消息在客户端应用程序和消息传递系 ...
- Kafka自我学习-报错篇
1. kafka启动出现:Unsupported major.minor version 52.0 错误, 具体的错误输出: Exception in thread "main" ...
- Kafka自我学习3-Scalable
1.After created the zookeeper cluster, we found all broker cluster topic can be find in zoo1, zoo2, ...
- Kafka自我学习2-Zookeeper cluster
Test enviroment : zoo1, zoo2, zoo3 cluster 1. Install zookeeper, package in kafka [root@zoo1 ~]# pwd ...
- Kafka自我学习1-Multi-broker cluster
====================================Testing environment =========================================== ...
- 大数据kafka视频教程 学习记录【B站尚硅谷 】
视频地址: https://www.bilibili.com/video/av35354301/?p=1 2019/03/06 21:59 消息队列的内部实现: Kafka基础: ...
随机推荐
- 逆向工程初步160个crackme-------2
有了第一个crackme的经验后,这个crackme用了半个小时就验证成功了.(思路和第一个crackme相似) 动态调试工具:ollydbg (2.10) 文件分析工具:PEID (0.95) 同样 ...
- wrk 及扩展支持 tcp 字节流协议压测
wrk 及扩展支持 tcp 字节流协议压测 高性能.方便使用的 HTTP(s) 的流量压测工具,结合了多个开源项目开发而成: redis 的 ae 事件框架 luajit openssl http-p ...
- MSSQL·查询T-SQL语句执行时间的三种方法
阅文时长 | 0.23分钟 字数统计 | 420.8字符 主要内容 | 1.引言&背景 2.自定义时间变量求差法 3.MSSQL内置方法 4.MSSQL选项开启时间统计 5.声明与参考资料 『 ...
- 技能Get·BOM头是什么?
阅文时长 | 0.26分钟 字数统计 | 472.8字符 主要内容 | 1.引言&背景 2.BOM头是什么? 3.如何创建或取消BOM头? 4.如何判断文件是否包含BOM头? 5.声明与参考资 ...
- Spring Cloud Alibaba Nacos Config 实战
Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持.使用 Spring Cloud Alibaba Nacos Config,您可 ...
- [刷题] 144 Binary Tree Preorder Traversal
要求 二叉树的前序遍历 实现 递归 栈模拟 定义结构体 Command 模拟指令,字符串s描述命令,树节点node为指令作用的节点 定义栈 Stack 存储命令 1 #include ...
- Sqoop 安装部署
1. 上传并解压 Sqoop 安装文件 将 sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz 安装包上传到 node-01 的 /root/ 目录下并将其解压 [root@no ...
- nosql数据库之Redis集群
Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施(installation). Redis 集群不支持那些需要同时处理多个键的 Redis 命令, 因为执行这些命令需要在多个 ...
- shell基础之99乘法表
方法一: 1 #!/bin/bash 2 for a in {1..9};do 3 for b in {1..9};do 4 c=`echo "$a*$b" |bc` 5 if [ ...
- 11.14 mii-tool:管理网络接口的状态
mii-tool命令用于查看.管理网络接口,默认情况下网卡的状态是自动协商的,但是有时也会出现不正常的情况,可以使用mii-tool进行调整. mii-tool [option] [interface ...