kafka学习笔记
Kafka原理篇
Kafka基本概念
Topic
- 主题。在 kafka 中,使用一个类别属性来划分消息的所属类,划分消息的这个类称为 topic。topic 相当于消息的分类标签,是一个逻辑概念。
Partition
- 分区。topic 中的消息被分割为一个或多个 partition,其是一个物理概念,对应到系统上就是一个或若干个目录。一个 topic 的 partition 数量是 broker 的整数倍。
- Kafka将topic划分为多个partition进行存储拥有两个好处:
- 消息存储扩容:一个文件的存储大小是有限的,但在集群中的多个文件的存储就可以大大增加一个topic能够保存的消息数量。
- 并行读写:通过多个partition文件存储消息,意味着producer和consumer可以并行的读写一个topic。
- 注意:下图是 topic 的解析,对于生产者顺序产生的消息,当随机写到不同的 partition 分区后,消费者在进行消费的时候是不能保证原来消息的顺序的。即消费者消费消息,会丢失顺序。所以,如果保证严格的一致性,那么可以使用单个 partition。
- Kafka 的消息组织方式实际上是三级结构:主题 - 分区 - 消息。主题下的每条消息只会保存在某一个分区中。
- 对数据进行分区的主要原因,就是为了实现系统的高伸缩性(Scalability)。不同的分区能够被放置到不同节点的机器上,而数据的读写操作也都是针对分区这个粒度而进行的,这样每个节点的机器都能独立地执行各自分区的读写请求处理。并且,我们还可以通过添加新的节点机器来增加整体系统的吞吐量。
- 除了提供负载均衡这种最核心的功能之外,利用分区也可以实现其他一些业务级别的需求,比如实现业务级别的消息顺序的问题。
segment
- 段。将partition进一步细分为了若干的 segment,每个 segment 文件的大小相等。文件大小可以设置。
Broker
- kafka 集群包含一个或多个服务器,每个服务器节点称为一个 broker。
- 假设某 topic 中有 N个 partition,集群中有 M 个 broker,则 broker 与 partition 间的关系:
- 若 N>=M,且 N 是 M 的整数倍,则每个 broker 上会平均存储(N/M)个该 topic 的多个 partition。
- 若 N>M,但 N 不是 M 的整数倍,则会出现 broker 上的 partition 分布不平均,导致 kafka 集群消息不均衡,导致各个 broker 任务不均衡,应尽量避免这种情况。
- 若 N<M,则会有 N 个 broker 上存储该 topic 的一个 partition,剩下的(M-N)个 broker 中没有存储该 topic 的 partition。
Producer
- 生产者。即消息的发布者,其会将某 topic 的消息发布到相应的 partition 中。生产者发送的消息默认会负载均衡地写入到该 topic 的各个 partition中。但是,也可以指定该生产者生产的消息存放的partition。
- 如果没有指定具体的partition号,那么Kafka Producer可以通过一定的算法计算出对应的partition号。
- 如果消息指定了key,则对key进行hash,然后映射到对应的partition号。
- 如果消息没有指定key,则使用Round Robin轮询算法来确定partition号,这样可以保证数据在所有的partition上平均分配。
- 另外,Kafka Producer也支持自定义的partition分配方式。客户端提供一个实现了 org.apache.kafka.clients.producer.Partitioner 的类,然后将此实现类配置到Producer中即可。
Consumer
- 消费者。可以从 broker 中读取消息。
- 一个消费者可以消费多个 topic 的消息。
- 一个消费者也可以消费同一个 topic 中的多个 partition 消息。
- 一个 partition 允许多个消费者同时消费。
Consumer Group
- Consumer Group 是 kafka 提供的可扩展且具有容错性的消费者机制。组内可以有多个消费者,它们共享一个公共的ID,即 group ID。组内的所有消费者协调在一起来消费订阅主题的所有分区。
- kafka 保证同一个 Consumer Group 中只有一个 Consumer 会消费某条消息,实际上,kafka 保证的是稳定状态下每一个 Consumer 实例只会消费某一个或多个特定的 partition,而某个 partition 的数据只会被某一个特定的 Consumer 实例所消费。
- N 个 partition可以被 N 个组消费 N 次,不能被 N 个组消费 M 次,其中 M 比 N 大。
- kafka保证了同一个消费组中只有一个消费者实例会消费某条消息,实际上,kafka保证的是稳定状态下每一个消费者实例只会消费一个或多个特定partition数据,而某个partition的数据只 会被某一特定的consumer实例消费,这样设计的劣势是无法让同一个消费组里的consumer均匀 消费,优势是每个consumer不用跟大量的broker通信,减少通信开销,也降低了分配难度。而 且,同一个partition数据是有序的,保证了有序被消费。
- consumer rebalance的控制策略是由每个consumer通过Zookeeper完成的。
Replicas of partition
- 分区副本。副本是一个分区的备份,是为了防止消息丢失而创建的分区的备份。
kafka副本定义
- 同一个分区下的所有副本保存有相同的消息序列,这些副本分散保存在不同的 Broker 上,从而能够对抗部分 Broker 宕机带来的数据不可用。
副本⻆色
- 采用基于领导者(Leader-based)的副本机制,确保副本中所有的数据都是一致,基于领导者的副本机制的工作原理如下图所示:
- 副本分成两类:领导者副本(Leader Replica)和追随者副本(Follower Replica)。每个分区在创建时都要选举一个副本,称为领导者副本,其余的副本自动称为追随者副本。
- 追随者副本是不对外提供服务的。这就是说,任何一个追随者副本都不能响应消费者和生产者的读写请求。所有的请求都必须由领导者副本来处理,或者说,所有的读写请求都必须发往领导者副本所在的 Broker,由该 Broker 负责处理。追随者副本不处理客户端请求,它唯一的任务就是从领导者副本异步拉取消息,并写入到自己的提交日志中,从而实现与领导者副本的同步。
- 当领导者副本挂掉了,或者说领导者副本所在的 Broker 宕机时,Kafka 依托于 ZooKeeper 提供的监控功能能够实时感知到,并立即开启新一轮的领导者选举,从追随者副本中选一个作为新的领导者。老 Leader 副本重启回来后,只能作为追随者副本加入到集群中。
为什么追随者副本是不对外提供服务?
- 方便实现“Read-your-writes”。所谓 Read-your-writes,顾名思义就是,当你使用生产者 API 向 Kafka 成功写入消息后,⻢上使用消费者 API 去读取刚才生产的消息。
- 方便实现单调读(Monotonic Reads)。什么是单调读呢?就是对于一个消费者用户而言,在多次消费消息时,它不会看到某条消息一会儿存在一会儿不存在。
如何创建
bin/kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic test
# 复制因子不能超过broker 数量
bin/kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 5 --partitions 1 --topic test2
Partition Leader
- 每个 partition 有多个副本,其中有且仅有一个作为 Leader,Leader 是当前负载消息读写的 partition。即所有读写操作只能发生于 Leader 分区上。
- partition leader就是broker Controller 选举出来的,ISR中的follower采用的是轮流坐庄的方式。
- 当 partition leader 宕机 ,则立⻢由 broker controller 从 follower 中选举出来一个新的 leader。其实所谓选举, 其实就是“按资排辈”。从 ISR 列表中找到第一个 follower 作为新的 leader。
Partition Follower
- 所有 Follower 都需要从 Leader 同步消息,Follower 与 Leader 始终保持消息同步。Leader 与 Follower 的关系是主备关系,而非主从关系。
- Partition Follower是通过Borker Controller 选举产生的。
ISR
- ISR,In-Sync Replicas,是指副本同步列表,Leader将从ISR这里面选,具有被选举权,没有选举权,Leader是由Broker Controller决定。是存放在 Zookeeper 中的。
- AR,Assigned Replicas,即所有的副本。在最初还没有 Leader 时 ISR = AR。
- OSR,Outof-Sync Replicas。同步过程中,发生延迟并且超过阈值(延迟时间可以设置)的副本将被踢出去,放到OSR。同时Broker Controller会定时发心跳检测所有的OSR,一旦符合条件了就可以再次进到ISR中。
- 数量关系:AR = ISR + OSR + Leader。
同步机制
- ISR 不只是追随者副本集合,它必然包括 Leader 副本。甚至在某些情况下,ISR 只有 Leader 这一个副本。
- Kafka 判断 Follower 是否与 Leader 同步的标准,不是看相差的消息数,而是另有“玄机”。
- 这个标准就是 Broker 端参数 replica.lag.time.max.ms 参数值。
- 这个参数的含义是 Follower 副本能够落后 Leader 副本的最⻓时间间隔,当前默认值是 10 秒。这就是说,只要一个 Follower 副本落后 Leader 副本的时间不连续超过 10 秒,那么 Kafka 就认为该Follower 副本与 Leader 是同步的,即使此时 Follower 副本中保存的消息明显少于 Leader 副本中的消息。
- ISR 是一个动态调整的集合,而非静态不变的。
思考:光是依靠多副本机制能保证Kafka的高可用性,但是能保证数据不丢失吗?
- 不行,因为如果leader宕机,但是leader的数据还没同步到follower上去,此时即使选举了follower作为新的leader,当时刚才的数据已经丢失了。
- ISR是:in-sync replica,就是跟leader partition保持同步的follower partition的数量,只有处于ISR列表中的follower才可以在leader宕机之后被选举为新的leader,因为在这个ISR列表里代表他的数据跟leader是同步的。
- 如果要保证写入kafka的数据不丢失,首先需要保证ISR中至少有一个follower,其次就是在一条数据写入了leader partition之后,要求必须复制给ISR中所有的follower partition,才能说代表这条数据已提交,绝对不会丢失,这是Kafka给出的承诺。
Unclean 领导者选举(Unclean Leader Election)
- Broker 端参数 unclean.leader.election.enable 控制是否允许 Unclean 领导者选举。
- false:必须等待ISR列表中有副本活过来才进行新的选举。该策略可靠性有保证,但可用性低。
- true:在ISR中没有副本的情况下可以选择任何一个该Topic的partition作为新的leader,该策略可用性高,但可靠性没有保证。
如果你听说过 CAP 理论的话,你一定知道,一个分布式系统通常只能同时满足一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)中的两个。显然,在这个问题上,Kafka 赋予你选择 C 或 A 的权利。
- 强烈建议你不要开启它,毕竟我们还可以通过其他的方式来提升高可用性。如果为了这点儿高可用性的改善,牺牲了数据一致性,那就非常不值当了。
offset
概述
- 偏移量。每条消息都有一个当前 Partition 下唯一的 64 字节的 offset,它是相对于当前分区第一条消息的偏移量。
- Consumer消费消息时,通过指定的offset来定位下一条要读取的消息。值得注意的是,offset的维护是由Consumer全权控制的。
- 当broker中配置的时间到达时,不论消息是否被消费,Kafka都会清理磁盘空间。<