在一个月黑风高的夜晚,突然收到现网生产环境
Kafka
消息积压的告警,梦中惊醒啊,马上起来排查日志。
问题现象:消费请求卡死在查找
Coordinator
Coordinator
为何物?
Coordinator
用于管理
Consumer Group
中各个成员,负责消费
offset
位移管理和
Consumer Rebalance
。
Consumer
在消费时必须先确认
Consumer Group
对应的
Coordinator
,随后才能
join Group
,获取对应的
topic partition
进行消费。
那如何确定
Consumer Group
的
Coordinator
呢?分两步走:
1
、一个
Consumer Group
对应一个
__consumers_offsets
的分区,首先先计算
Consumer Group
对应的
__consumers_offsets
的分区,计算公式如下:
__consumers_offsets partition# = Math.abs(groupId.hashCode() % groupMetadataTopicPartitionCount
,其中
groupMetadataTopicPartitionCount
由
offsets.topic.num.partitions
指定。
2
、
1
中计算的该
partition
的
leader
所在的
broker
就是被选定的
Coordinator
。
定位过程
Coordinator
节点找到了,现在看看
Coordinator
是否有问题:
不出所料,
Coordinator
对应分区
Leader
为
-1
,消费端程序会一直等待,直到
Leader
选出来为止,这就直接导致了消费卡死。
为啥
Leader
无法选举?
Leader
选举是由
Controller
负责的。
Controller
节点负责管理整个集群中分区和副本的状态,比如
partition
的
Leader
选举,
topic
创建,副本分配,
partition
和
replica
扩容等。现在我们看看
Controller
的日志:
1.
6
月
10
日
15:48:30,006
秒
Broker 1
成为
controller
此时感知的节点为
1
和
2
,节点
3
在
zk
读不出来:
31
秒
847
的时候把
__consumer_offsets
的分区
3
的
Leader
选为
1
,
ISR
为
[1,2]
,
leader_epoch
为
14
:
再过
1
秒后才感知到
Controller
发生变化,自身清退
2.
Broker 2
在其后几百毫秒后
(15:48:30,936)
也成为
Controller
但是
Broker2
是感知到
Broker 3
节点是活的,日志如下
:
注意这个时间点,
Broker1
还没在
zk
把
__consumer_offsets
的分区
3
的
Leader
从节点
3
改为
1
,这样
Broker 2
还认为
Broker 3
是
Leader
,并且
Broker 3
在它认为是活的,所以不需要重新选举
Leader
。这样一直保持了相当长的时间,即使
Broker 1
已经把这个分区的
Leader
切换了,它也不感知。
3.
Broker 2
在
12
号的
21:43:19
又感知
Broker 1
网络中断,并处理节点失败事件:
因为
Broker 2
内存中认为
__consumer_offsets
分区
3
的
Leader
是
broker 3
,所以不会触发分区
3
的
Leader
切换。
Broker 2
但是在处理失败的节点
Broker 1
时,会把副本从
ISR
列表中去掉,去掉前会读一次
zk
,代码如下:
但是发现
zk
中分区
3
的
Leader
已经变为
1
,
ISR
列表为
[1,2]
,当要去掉的节点
1
就是
Leader
的时候,
Leader
就会变为
-1
,
ISR
只有
[2]
,从日志也可以看到:
这样分区
3
的
Leader
一直为
-1
,直到有新的事件触发节点
2
重新选举才能恢复(例如重启某个节点)。
根因总结
出现网络异常后,由于新老
controller
之间感知的可用节点不同,导致新
controller
对某个分区的
Leader
在内存中的信息与
zk
记录元数据的信息不一致,导致
controller
选举流程出现错误,选不出
Leader
。
需要有新的选举事件才能触发
Leader
选出来,例如重启。
问题总结
这是一个典型的由于网络异常导致脑裂,进而出现了多个
Controller
,菊厂分布式消息服务
Kafka(
https://www.huaweicloud.com/product/dmskafka.html
)
经过电信级的可靠性验证,已经完美解决了这些问题
。