图示
生产消费过程
Partition Leader 和 Partition Follower之间的关系
Partition中消息的追加方式
0. 基础知识
0.1 名词解释
Cluster(集群)
Broker(代理) , 每一个Server叫一个Broker
Producer(生产者)
Consumer(消费者)
Topic(逻辑分区), 每一类消息会落入不同的topic类中
Partition(物理分区)
Segment(段),最小分区, 含有index和log文件
Zookeeper(分布式应用程序协调服务)
Lag(消费滞后)
Rebalance(平衡)
Append(追加)
Offset(偏移量)
Coodinator 协调者
HW(high watermark),这是一个分区的最后一条消息的offset
ACK(Acknowledgement)接收站发给发送站的一种传输类控制字符。表示发来的数据已确认接收无误
SYN 同步序列编号(Synchronize Sequence Numbers)。是TCP/IP建立连接时使用的握手信号
ISR同步副本 (in-sync replicas)。ISR的副本保持和leader的同步,当然leader本身也在ISR中
0.2 消息队列
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合、异步消息、流量削锋等问题。实现高性能、高可用、可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。
目前在生产环境,使用较多的消息队列有ActiveMQ、RabbitMQ、ZeroMQ、Kafka、MetaMQ、RocketMQ等。
0.3 Kafka存活的条件
1.必须维护与Zookeeper的session(这个通过Zookeeper的Heartbeat机制来实现)
2.Follower必须能够及时将Leader的消息复制过来,不能“落后太多”
Leader会跟踪与其保持同步的Replica列表,该列表称为ISR(即in-sync Replica)
//replica.lag.max.messages配置,其默认值是4000 允许落后的最大值
//replica.lag.time.max.ms来配置,其默认值是10000 允许的最大超时时间
1. Broker
1.1 Leader选举
Zookeeper 主要用来跟踪Kafka 集群中的节点状态, 以及Kafka Topic, message 等等其他信息. 同时, Kafka 依赖于Zookeeper, 没有Zookeeper 是不能运行起来Kafka 的.
Kafka 通过 Zookeeper 管理集群配置,选举 leader,以及在 consumer group 发生变化时进行 rebalance
1.Controller 选举:
Controller 是一个特殊的Broker, 其负责所有Partition 的leader/follower 关系.
记录集群中都有哪些活跃着的Broker.
Zookeeper 负责从Broker 中选举出一个作为Controller, 并确保其唯一性. 同时, 当Controller 宕机时, 选举一个新的.
当broker启动的时候,都会创建KafkaController对象
这些每个节点上的KafkaController会在指定的zookeeper路径下创建临时节点,只有第一个成功创建的节点的KafkaController才可以成为leader,其余的都是follower
Broker1=>被选举为Controller Leader, 这个Broker1 负责管理整个集群中分区和副本的状态
Broker2 => 其余每个单独的server叫做Replica Manager
Broker3
2.Topic 配置:
有哪些Topic, Topic 都有哪些Partition, Replica 存放在哪里, Leader 是谁.
1.2 Topic
Partition
文件存储
1.会根据 partition 规则选择被存储到哪一个 partition。
2.顺序追加到log中
3.每条消息在log文件中的位置成为offset(偏移量),offset为一个long型数字,唯一标记一条消息,
文件复制和同步
1.Producer只将该消息发送到该Partition的Leader , Consumer读消息也是从Leader读取
2. partition有n个副本...
N 个 replicas 中,其中一个 replica 为 leader,其他都为 follower
leader 处理 partition 的所有读写请求,与此同时,follower 会被动定期地去复制 leader 上的数据
副本个数N = leader + follower1 + follower2....
leader挂了, 会从follower中 重新选举一个leader
3.Leader =>将消息 =>写入本地Log
4.Follower => pull 消息=> Leader , 写入其Log后,向Leader发送ACK
//为了提高性能,每个Follower在接收到数据后就立马向Leader发送ACK,而非等到数据写入Log中
因此,对于已经commit的消息,Kafka只能保证它被存于多个Replica的内存中,而不能保证它们被持久化到磁盘中
也就不能完全保证异常发生后该条消息一定能被Consumer消费
5.一旦Leader收到了ISR中的所有Replica的ACK,该消息就被认为已经commit了,Leader将增加HW并且向Producer发送ACK
2. Consumer
2.1 位移管理
1.kafka会定期把group消费情况保存起来,做成一个offset map
2.将offset信息写入 __consumer_offsets topic, 这个topic 保存了每个consumer group某一时刻提交的offset信息
2.2 Rebalance的概念
1.rebalance本质上是一种协议,规定了一个consumer group下的所有consumer如何达成一致来分配订阅topic的每个分区。
比如某个group下有20个consumer,它订阅了一个具有100个分区的topic。正常情况下,Kafka平均会为每个consumer分配5个分区。这个分配的过程就叫rebalance。
2.3 Rebalance的时机
组成员发生变更(新consumer加入组、已有consumer主动离开组或已有consumer崩溃了——这两者的区别后面会谈到)
订阅主题数发生变更——这当然是可能的,如果你使用了正则表达式的方式进行订阅,那么新建匹配正则表达式的topic就会触发rebalance
订阅主题的分区数发生变更
2.4 Rebalance的过程
1.JoinGroup
consumer1 => 发送订阅信息,并请求入组 => coordinator => 选择consumer1作为leader, 并发送给c1成员信息和订阅信息, 让其负责 "消费分配方案的制定"
consumer2 => 发送订阅信息,并请求入组 => coordinator => 告诉c2,你们组leader是c1
2.SyncGroup
consumer1 => 发送分配消费的方案 => coordinator => 下发方案给c1
consumer2 => 发送分配消费的方案(非leader 内容为空) => coordinator => 下发方案给c1
2.5 谁来执行rebalance和consumer group管理
1.Coordinator来执行对于consumer group的管理。
2.先确定consumer group位移信息写入__consumers_offsets的哪个分区, 则该分区leader 所在的broker 就是被选定的coordinator
3. Zookeeper
3.1 组件
KafkaController: 负责管理整个集群中分区和副本的状态
ReplicaManager:负责管理当前broker所有分区和副本的信息,会处理KafkaController发起的一些请求,副本状态的切换,添加/读取消息等
ZookeeperLeaderElector: 主要用于KafkController Leader选举
ControllerContext: 维护了controller需要用到的上下文,同时也缓存一些zookeeper数据,包括可用的broker,全部的topic,分区和副本信息
ControllerChannelManager: 维护Controller Leader与集群中其他broker之间连接,是管理这个集群的基础
TopicDeletionManager: 用于删除指定的topic
PartitionStateMachine: 用于管理集群所有partition状态的状态机
ReplicaStateMachine: 用于管理集群中所有副本状态的状态机
ControllerBrokerRequestBatch: 实现了向broker批量发送请求的功能
PartitionLeaderSelector:选举leader副本的选举策略
IzkChildListener:是zookeeper上的监听器,实现了对zookeeper上某些节点数据,子节点或者session状态的监听,被处罚后调用对应的业务逻辑
li.li1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}ul.ul1 {list-style-type: disc}
li.li1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}ul.ul1 {list-style-type: disc}
li.li1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}ul.ul1 {list-style-type: disc}
li.li1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}ul.ul1 {list-style-type: disc}
li.li1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}ul.ul1 {list-style-type: disc}