Skip to content

Commit a1dedcd

Browse files
committed
优化
1 parent de5de44 commit a1dedcd

4 files changed

Lines changed: 120 additions & 32 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ Kafka / RocketMQ 消息系统源码
8080
![kafka_architecture](https://github.com/coderbruis/JavaSourceCodeLearning/releases/download/images-v1/kafka_architecture.png)
8181

8282
<strong>Kafka Rebalance流程图</strong>
83-
![Kafka Cooperative Rebalance](https://github.com/coderbruis/JavaSourceCodeLearning/releases/download/images-v1/kafka_COOPERATIVE_rebalance.png)
84-
8583
![Kafka EAGER Rebalance](https://github.com/coderbruis/JavaSourceCodeLearning/releases/download/images-v1/kafka_EAGER_rebalance.png)
8684

85+
![Kafka Cooperative Rebalance](https://github.com/coderbruis/JavaSourceCodeLearning/releases/download/images-v1/kafka_COOPERATIVE_rebalance.png)
86+
8787
<strong>Kafka ISR / HW / LEO关系图</strong>
8888
![Kafka_HW_ISR_LEO](https://github.com/coderbruis/JavaSourceCodeLearning/releases/download/images-v1/kafka_HW_ISR_LEO.png)
8989

@@ -100,7 +100,7 @@ Kafka / RocketMQ 消息系统源码
100100
- [深入分析 ThreadLocal](https://github.com/coderbruis/JavaSourceCodeLearning/blob/master/note/JDK/%E6%B7%B1%E5%85%A5%E5%88%86%E6%9E%90ThreadLocal.md)
101101
- [深入学习 Java volatile 关键字](https://github.com/coderbruis/JavaSourceLearning/blob/master/note/JDK/%E6%B7%B1%E5%85%A5%E5%AD%A6%E4%B9%A0Java%20volatile%E5%85%B3%E9%94%AE%E5%AD%97.md)
102102
- [深入学习 Thread 底层原理](https://github.com/coderbruis/JavaSourceCodeLearning/blob/master/note/JDK/%E6%B7%B1%E5%85%A5%E5%AD%A6%E4%B9%A0Thread%E5%BA%95%E5%B1%82%E6%BA%90%E7%A0%81.md)
103-
- [深入学习HashMap 底层源码与原理]()
103+
- [深入学习HashMap 底层源码与原理](https://github.com/coderbruis/JavaSourceCodeLearning/blob/master/note/JDK/HashMap%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90.md)
104104
- [开源项目里那些看不懂的位运算分析](https://github.com/coderbruis/JavaSourceCodeLearning/blob/master/note/JDK/%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%E9%87%8C%E9%82%A3%E4%BA%9B%E7%9C%8B%E4%B8%8D%E6%87%82%E7%9A%84%E4%BD%8D%E8%BF%90%E7%AE%97%E5%88%86%E6%9E%90.md)
105105
- [ThreadPoolExecutor 源码分析](https://github.com/coderbruis/JavaSourceCodeLearning/blob/master/note/JDK/%E6%B7%B1%E5%85%A5%E8%A7%A3%E6%9E%90ThreadPoolExecutor%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86.md)
106106

note/JDK/HashMap源码分析.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
当前HashMap版本:JDK1.8
1+
+ 当前HashMap版本:JDK1.8
2+
+ 转载请标明出处
3+
4+
# HashMap底层原理图
5+
![HashMap原理图](https://github.com/coderbruis/JavaSourceCodeLearning/releases/download/images-v1/HashMap.png)
26

37
# HashMap的重要成员变量以及内部类
48
> **默认容量:DEFAULT_INITIAL_CAPACITY**

note/kafka/Kafka ISR 底层原理.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
+ 当前分析版本是kafka最新版本(版本随时变化,最新分析代码请关注仓库:https://github.com/coderbruis/kafka source_code_analysis分支,底层原理持续更新)
22
+ 转载请标明出处
33

4+
# Kafka HW,ISR,LEO关系图
5+
6+
![Kafka_HW_ISR_LEO](https://github.com/coderbruis/JavaSourceCodeLearning/releases/download/images-v1/kafka_HW_ISR_LEO.png)
7+
48
# Kafka ISR是什么?解决什么问题?
59
## 是什么?
610
Kafka ISR是In-Sync Replicas,意思是“与leader保持同步的副本集合”。在Kafka中会有leader副本和follower副本,下面举例:
Lines changed: 108 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
+ 当前分析版本是kafka最新版本(版本随时变化,最新分析代码请关注仓库:[https://github.com/coderbruis/kafka](https://github.com/coderbruis/kafka) **<font style="color:#DF2A3F;">source_code_analysis分支</font>**,底层原理持续更新)
22
+ 转载请标明出处
33

4+
# Kafka Rebalance流程图
5+
6+
![Kafka EAGER Rebalance](https://github.com/coderbruis/JavaSourceCodeLearning/releases/download/images-v1/kafka_EAGER_rebalance.png)
7+
8+
![Kafka Cooperative Rebalance](https://github.com/coderbruis/JavaSourceCodeLearning/releases/download/images-v1/kafka_COOPERATIVE_rebalance.png)
9+
410
# Kafka Rebalance 核心流程
511
`KafkaConsumer.poll()` 是消费者触发 rebalance 的主要入口。
612

@@ -629,20 +635,47 @@ if (protocol == RebalanceProtocol.COOPERATIVE &&
629635

630636
# EAGER 和 COOPERATIVE 的差异
631637
## EAGER
632-
EAGER rebalance 的特点是简单直接。
638+
EAGER核心特点:全量停、全量分、再恢复
639+
640+
### EAGER Rebalance流程
641+
642+
第一步:触发 Rebalance
643+
1. 成员变化:join / leave / session timeout / max.poll.interval 超时等。
644+
2. 订阅或元数据变化:订阅 topic 变化、正则订阅匹配变化、partition 数变化等。
645+
646+
第二步:Coordinator 进入 Rebalance 状态
647+
1. Coordinator 将 group 状态切到 PreparingRebalance(可能不是第一次进入rebalance,所以这里状态已经是PreparingRebalance了,正常第一次是在JoinGroup进入Coordinator里,会将状态变更为PreparingRebalance。)
648+
2. 现有成员会通过 heartbeat 或 poll 流程感知需要重新加入 group。
649+
3. 新成员或需要重分配的成员准备发送 JoinGroupRequest。
650+
651+
第三步:EAGER 全员撤销旧 assignment,然后 JoinGroup
652+
1. 每个 consumer 在 JoinGroup 前执行 onJoinPrepare。
653+
2. EAGER 协议下 revoke 当前持有的所有 partitions。
654+
3. 调用 onPartitionsRevoked(allAssignedPartitions)。
655+
4. 清空本地 assignment,停止这些 partitions 的消费。全组成员进入消费暂停状态(STW)。
656+
5. 向 coordinator 发送 JoinGroupRequest,携带 subscription 和支持的 assignor。
657+
658+
第四步:JoinGroup 完成成员协商
659+
1. Coordinator 收集本轮成员的 JoinGroupRequest。
660+
2. 选择 leader consumer。
661+
3. 选择 assignment strategy / protocol,leader consumer生成新的assignment。
662+
4. 生成新的 generationId,同时将group状态变更为COMPLETING_REBALANCE。
663+
5. JoinGroupResponse 返回给成员。
664+
6. Leader 会拿到所有成员的 subscription metadata。
665+
666+
第五步:分配 + SyncGroup
667+
1. Leader consumer 执行分配算法,比如 Range / Sticky。
668+
2. Leader 通过 SyncGroupRequest 把全组 assignment 发给 coordinator。
669+
3. Follower 也发送 SyncGroupRequest,但通常不带 assignment。
670+
4. Coordinator 保存本轮 assignment,group状态变更为STABLE。
671+
5. Coordinator 通过各自的 SyncGroupResponse 返回每个 consumer 自己的 assignment。
672+
673+
第六步:恢复消费
674+
1. Consumer 收到自己的 assignment。
675+
2. 更新本地 assignment。
676+
3. 调用 onPartitionsAssigned(newAssignedPartitions)。
677+
4. 从对应 offset 开始拉取消息,恢复消费。
633678

634-
```plain
635-
onJoinPrepare:
636-
revoke all partitions
637-
clear local assignment
638-
639-
leader assign:
640-
assign all partitions again
641-
642-
onJoinComplete:
643-
assign new partitions
644-
trigger onPartitionsAssigned
645-
```
646679

647680
优点:
648681

@@ -655,23 +688,70 @@ onJoinComplete:
655688
+ 即使某些 partition 仍然分给同一个 consumer,也会先 revoke 再 assign。
656689

657690
## COOPERATIVE
658-
COOPERATIVE rebalance 的特点是渐进迁移。
659-
660-
```plain
661-
onJoinPrepare:
662-
keep still-owned partitions
663-
revoke only obviously invalid partitions
691+
COOPERATIVE rebalance 的特点是渐进迁移,不会撤销所有分区导致全部分区STW。
692+
693+
### COOPERATIVE Rebalance流程
694+
695+
第一轮:标记迁移,旧 owner revoke(onwer表示持有parition的consumer)
696+
1. 成员变化、订阅变化或元数据变化触发 rebalance。
697+
2. consumer 发送 JoinGroup 给 coordinator。
698+
JoinGroup metadata 里包含:
699+
○ 当前 subscription
700+
○ 当前本地已分配分区,也就是 ownedPartitions
701+
3. coordinator 收集所有成员的 JoinGroup。
702+
coordinator 负责:
703+
○ 选 leader
704+
○ 选 assignor/protocol
705+
○ 把所有成员 subscription metadata 返回给 leader
706+
coordinator收集完所有的JoinGroup请求之后,会进入新的generationId(递增)。
707+
4. leader consumer 执行 assignor。
708+
CooperativeStickyAssignor 会:
709+
○ 先计算目标 assignment
710+
○ 如果某个分区要从旧 owner 转给新 owner
711+
○ 但旧 owner 在本轮 JoinGroup 里仍上报该分区为 owned
712+
○ 那么本轮不会把该分区分给新 owner
713+
○ 同时旧 owner 的本轮 assignment 不再包含该分区
714+
5. leader Consumer 通过 SyncGroup 把全组 assignment 提交给 coordinator。其他consumer也会发送一个空的SyncGroup给coorinator
715+
6. coordinator 保存 assignment,并通过 SyncGroupResponse 返回每个 consumer 自己的 assignment。
716+
7. consumer 处理 SyncGroupResponse。
717+
本地计算:
718+
```text
719+
owned = 当前本地 assignment
720+
assigned = 本轮收到的 assignment
721+
722+
revoked = owned - assigned
723+
added = assigned - owned
724+
```
725+
726+
需要注意,第一轮主要是做撤销,但是也可能直接添加新的分区分配结果。因为如果这一轮有某个分区本来就没有旧onwer(旧的持有这个parition的consumer),这一轮就可以直接分配给新onwer。
727+
8. 如果 revoked 非空:
728+
○ 调用 onPartitionsRevoked(revoked)
729+
○ 调用 requestRejoin()
730+
○ 后续把本地 assignment 更新为 assigned
731+
9. 如果 added 非空:
732+
○ 调用 onPartitionsAssigned(added)
733+
注意:正在从旧 owner 转移给新 owner 的分区,第一轮不会出现在新 owner 的 added 里。
734+
第二轮:旧owner撤销分区,新owner获得第一轮撤销的分区
735+
1. 因为第一轮有 consumer 调用了 requestRejoin(),group 再次 rebalance。
736+
2. consumer 再次发送 JoinGroup。
737+
此时旧 owner 的本地 assignment 已经更新,所以它上报的 ownedPartitions 不再包含刚刚 revoked 的分区。
738+
被撤销的分区不会通过JoinGroup发送给Coordinator,revokeList和addLIst都是通过集合计算来得出的。
739+
coordinator收集完所有的JoinGroup请求之后,会进入新的generationId(递增)。
740+
3. coordinator 再次收集成员,选 leader,选协议。
741+
然后将所有成员 subscription metadata 返回给 leader consumer。
742+
4. leader 再次执行 assignor。
743+
这次 assignor 发现:
744+
○ 该分区已经没有旧 owner 上报 owned
745+
○ 可以安全分配给新 owner
746+
5. leader 通过 SyncGroup 提交新的全组 assignment。
747+
6. coordinator 通过 SyncGroupResponse 返回各成员自己的 assignment。
748+
7. 新 owner 处理 assignment。
749+
本地计算:
750+
added = assigned - owned
751+
8. 新 owner 对新增分区调用:
752+
onPartitionsAssigned(added)
664753

665-
leader assign:
666-
do not immediately reassign partitions still owned by others
667754

668-
onJoinComplete:
669-
revoke partitions that need migration
670-
request another rejoin if needed
671-
672-
next rebalance:
673-
assign released partitions to new owners
674-
```
675755

676756
优点:
677757

0 commit comments

Comments
 (0)