Kafka
下面这篇文章很棒:文章地址
该链接主要内容:
Kafka集群中的其中一个Broker会被选举为Controller
一个topic可具有多个partition,但Partition一定属于一个topic。
- 消费时,每个消费线程最多只能使用一个partition。
- 一个topic中partition的数量,就是每个user group中消费该topic的最大并行度数量。(Partition则是Consumer消费的基本单元,即topic1有几个partition,那么最多就可以有多少个consumer同时在一个User Group里消费这个topic)
为了便于实现MQ中的多播,重复消费等引入的概念。如果ConsumerA以及ConsumerB同在一个UserGroup,那么ConsumerA消费的数据ConsumerB就无法消费了。即:所有usergroup中的consumer使用一套offset。
User1,User2同属一个userGroup时,即表示二者共用一套Offset。因每个partition 的offset只能由一个线程维护,因此注定了每个UserGroup里只能有一个消费线程对一个partition进行消费。
Offset专指Partition以及User Group而言,记录某个user group在某个partiton中当前已经消费到达的位置。
kafkaServer(broker)不直接负责每个consumer的当前消费到了哪里,所以需要client端和zk联合维护每个partition读到了哪里,即Offset。
大部分消息都会被顺序读取,当然也会存在少量的随机读取消息(比如处理的时候这条消息处理失败,需要重新处理)。所以索引在这里的意义仅为简单支持少量随机查询。所以在索引的实现上,基本上就是为了支持针对某个Offset进行二分查找而存在的索引。
Kafka自己的In-Sync Replicas(ISR)机制
“以一段时间而非以一个消息为基本单位,进行可靠性保障”这是ISR机制最核心的思想
controller在启动时会注册zk监听器来监听zookeeper中的/brokers/ids节点下子节点的变化,即集群所有broker列表,而每台broker在启动时会向zk的/brokers/ids下写入一个名为broker.id的临时节点,当该broker挂掉或与zk断开连接时,此临时节点会被移除(这是zk提供的功能),之后controller端的监听器就会自动感知到这个变化并将BrokerChange事件写入到controller上的请求阻塞队列中。
一旦controller端从阻塞队列中获取到该事件,它会开启BrokerChange事件的处理逻辑,具体包含:
1. 获取当前存活的所有broker列表
2. 根据之前缓存的broker列表计算出当前“已挂掉”的broker列表
3. 更新controller端缓存
4. 对于当前所有存活的broker,更新元数据信息并且启动新broker上的分区和副本
5. 对于“挂掉”的那些broker,处理这些broker上的分区副本(标记为offline以及执行offline逻辑并更新元数据等)
至于zk为什么会知道是否失连,zk -> kafka 搭建服务的时候,你自己设置的心跳时间,如果超过心跳时间没有连接到就会断开连接。