Kafka系统基本架构
自我推导设计:
- kafka 是用来存数据
- 现实世界数据有分类,所以存储系统也应有数据分类管理功能,如 mysql 的表;kafka 有 topic;
- 如一个 topic 的数据全部交给一台 server 存储和管理,则读写吞吐量有限
- 所以,一个 topic 的数据应该可以分成多个部分(partition)分别交给多台 server存储和管理;
- 如一台 server 宕机,这台 server 负责的 partition 将不可用,所以,一个 partition 应有多个副本;
- 一个 partition 有多个副本,则副本间的数据一致性难以保证,因此要有一个 leader 统领读写;
- 一个 leader 万一挂掉,则该 partition 又不可用,因此还要有 leader 的动态选举机制;
- 集群有哪些 topic,topic 有哪几个分区,server 在线情况,等等元信息和状态信息需要在集群内部及客户端之间共享,则引入了 zookeeper;
- 客户端在读取数据时,往往需要知道自己所读取到的位置,因而要引入消息偏移量维护机制;
broker 服务器
一台 kafka 服务器就是一个 broker。一个 kafka 集群由多个 broker 组成。
生产者 producer
消息生产者,就是向 kafka broker 发消息的客户端。
消费者 consumer
consumer :消费者,从 kafka broker 取消息的客户端。
consumer group:消费组,单个或多个 consumer 可以组成一个消费组;
消费组是用来实现消息的广播(发给所有的 consumer)和单播(发给任意一个 consumer)的手段
消费者可以对消费到的消息位置(消息偏移量)进行记录;
老版本是记录在 zookeeper 中;新版本是记录在 kafka 中一个内置的 topic 中(__consumer_offsets)
主题 topic 和分区 partition
topic
Kafka 中存储数据的逻辑分类;你可以理解为数据库中“表”的概念;
比如,将 app 端日志、微信小程序端日志、业务库订单表数据分别放入不同的 topic
partition 分区
topic 中数据的具体管理单元;
- 每个 partition 由一个 kafka broker 服务器管理;
- 每个 topic 可以划分为多个 partition,分布到多个 broker 上管理;
- 每个 partition 都可以有多个副本;
分区对于 kafka 集群的好处是:实现 topic 数据的负载均衡。提高写入、读出的并发度,提高吞吐量。
分区副本 replica
每个 topic 的每个 partition 都可以配置多个副本(replica),以提高数据的可靠性;
每个 partition 的所有副本中,必有一个 leader 副本,其他的就是 follower 副本(observer 副本);follower
定期找 leader 同步最新的数据;对外提供服务只有 leader;
分区 leader
partition replica 中的一个角色,在一个 partition 的多个副本中,会存在一个副本角色为 leader;
producer 和 consumer 只能跟 leader 交互(读写数据)。
分区 follower
partition replica 中的一个角色,它通过心跳通信不断从 leader 中拉取、复制数据(只负责备份)。
如果 leader 所在节点宕机,follower 中会选举出新的 leader;
消息偏移量 offset
partition 中每条消息都会被分配一个递增 id(offset);通过 offset 可以快速定位到消息的存储位置;
kafka 只保证按一个 partition 中的消息的顺序,不保证一个 topic 的整体(多个 partition 间)的顺序。
因为broker将数据写入分区存储文件时,永远都是追加,所以kafka把自己的数据存储文件称之为log。
ISR 同步副本列表
ISR 概念:(同步副本)。每个分区的 leader 会维护一个 ISR 列表,ISR 列表里面就是 follower 副本的 Borker 编 号 , 只 有 跟 得 上 Leader 的 follower 副 本 才 能 加 入 到 ISR 里 面 , 这 个 是 通 过replica.lag.time.max.ms =10000(默认值)参数配置的,只有 ISR 里的成员才有被选为 leader 的可能
踢出 ISR 和重新加入 ISR 的条件:
- 踢出 ISR 的条件: 由 replica.lag.time.max.ms =10000 决定,如上图;
- 重新加入 ISR 的条件: OSR 副本的 LEO(log end offset)追上 leader 的 LEO;
kafka 的数据存储结构
物理存储目录结构
- 存储目录 名称规范: topic 名称-分区号
注:“t1"即为一个 topic 的名称;
而“t1-0 / t1-1"则表明这个目录是 t1 这个 topic 的哪个 partition;
- 数据文件 名称规范:
生产者生产的消息会不断追加到 log 文件末尾,为防止 log 文件过大导致数据定位效率低下,Kafka采取了分片和索引机制 ;
- 每个 partition 的数据将分为多个 segment 存储
- 每个 segment 对应两个文件:“.index"文件和“.log"文件。
index 和 log 文件以当前 segment 的第一条消息的 offset。
index 索引文件中的数据为: 消息 offset -> log 文件中该消息的物理偏移量位置;
Kafka 中的索引文件以稀疏索引( sparse index )的方式构造消息的索引,它并不保证每个消息在索引文件中都有对应的索引;每当写入一定量(由 broker 端参数 log.index.interval.bytes 指定,默认值为 4096 ,即 4KB )的消息时,偏移量索引文件和时间戳索引文件分别增加一个偏移量索引项和时间戳索引项,增大或减小 log.index.interval.bytes 的值,对应地可以缩小或增加索引项的密度;
查询指定偏移量时,使用二分查找法来快速定位偏移量的位置。
消息 message 存储结构
在客户端编程代码中,消息的封装类有两种:ProducerRecord、ConsumerRecord;
简单来说,kafka 中的每个 massage 由一对 key-value 构成:
Kafka 中的 message 格式经历了 3 个版本的变化了:v0 、 v1 、 v2
各个字段的含义介绍如下:
- crc:占用 4 个字节,主要用于校验消息的内容;(循环冗余校验码)
- magic:这个占用 1 个字节,主要用于标识 Kafka 版本。Kafka 0.10.x magic 默认值为 1;
- attributes:占用 1 个字节,这里面存储了消息压缩使用的编码以及 Timestamp 类型。目前 Kafka 支持 gzip、snappy 以及 lz4(0.8.2 引入) 三种压缩格式;[0,1,2]三位 it 表示压缩类型。[3]位表示时间错类型(0,create time;1,append time),[4,5,6,7]位保留;
- key length:占用 4 个字节。主要标识 Key 的内容的长度;
- key:占用 N 个字节,存储的是 key 的具体内容;(相当于读多少位之后这个就是key,知道key有多长就能读对key)
- value length:占用 4 个字节。主要标识 value的内容的长度;
- value:value 即是消息的真实内容,在 Kafka 中这个也叫做 payload。(知道value有多长就能读对value)
通过这些设置,在发送的时候,如果网络中出现了波动,那么我们就能够知道消息是有问题的。
探究Kafka原理-5.Kafka设计原理和生产者原理解析(下):https://developer.aliyun.com/article/1413724