kafka宕机恢复

kafka在我们的系统中处于一个消息集散地的位置,非常重要,一旦出问题,整个系统的数据处理就会停止.
我原来的理解是这样的,kafka每个patition都有副本,所以一旦某个kafka服务器宕机,该服务器上的partition副本就会迁移到其它服务器。但实际情况不是这样的。我在三台虚拟机上建立了kafka集群(版本: kafka_2.12-1.1.0, 操作系统redhat6.3)
192.168.6.20 brokerid:0
192.168.6.21 brokerid:1
192.168.6.22 brokerid:2
然后把192.168.6.21上的kafka停止。这时候看kafka上有哪些找不到的partition:
[root@s20 bin]# ./kafka-topics.sh --zookeeper  192.168.6.20:2181  --describe --unavailable-partitions
        Topic: pc_akcs   Partition: 1    Leader: -1      Replicas: 0,2,1 Isr: 1
        Topic: pc_exp_mig33vokip Partition: 0    Leader: -1      Replicas: 0,1   Isr: 1
        Topic: pc_exp_skmpp      Partition: 1    Leader: -1      Replicas: 0,1   Isr: 1
        Topic: pc_exp_skvkoip     Partition: 0    Leader: -1      Replicas: 0,1   Isr: 1
        Topic: pc_exp_vkoikp_del  Partition: 2    Leader: -1      Replicas: 0,1   Isr: 1
        Topic: pc_gktp   Partition: 0    Leader: -1      Replicas: 2,0,1 Isr: 1
        Topic: pc_tk125  Partition: 0    Leader: -1      Replicas: 0,1   Isr: 1

其中下面这两行并不是最初的状态,文章是补写的。这两行的Replicas现在是三个,当时应该是两个,其中一个是1。
        Topic: pc_gktp   Partition: 0    Leader: -1      Replicas: 2,0,1 Isr: 1
        Topic: pc_akcs   Partition: 1    Leader: -1      Replicas: 0,2,1 Isr: 1
        
分析上面的结果:
有7个partition找不到。这7个partition不是没有数据,例如:
Topic: pc_exp_skmpp      Partition: 1    Leader: -1      Replicas: 0,1   Isr: 1
pc_exp_skmpp的partition 1有两个副本,位于broker 0和1,broker 1停了,但broker 0还在。

正常的处理逻辑应该是broker 1联系不上,broker 0上的副本接替当leader, kafka在broker 2上新建副本.
但是上面的partition上,上面的逻辑并没有发生。共有的现象:
Leader: -1       -----leader是-1,  
Replicas: 0,1   -----有一个副本还在失效的broker上(为什么没有“1,2”这样的组合?)
Isr: 1           -----Isr的副本在失效的副本上

这些没有leader的partition导致storm worker不断挂起:
2019-05-24 11:24:16.944 o.a.s.util Thread-25-Spout4bcp_skmpp-executor[61 61] [ERROR] Halting process: ("Worker died")
java.lang.RuntimeException: ("Worker died")
        at org.apache.storm.util$exit_process_BANG_.doInvoke(util.clj:341) [storm-core-1.2.1.jar:1.2.1]
        at clojure.lang.RestFn.invoke(RestFn.java:423) [clojure-1.7.0.jar:?]
        at org.apache.storm.daemon.worker$fn__5649$fn__5650.invoke(worker.clj:781) [storm-core-1.2.1.jar:1.2.1]
        at org.apache.storm.daemon.executor$mk_executor_data$fn__4860$fn__4861.invoke(executor.clj:281) [storm-core-1.2.1.jar:1.
2.1]
        at org.apache.storm.util$async_loop$fn__557.invoke(util.clj:494) [storm-core-1.2.1.jar:1.2.1]
        at clojure.lang.AFn.run(AFn.java:22) [clojure-1.7.0.jar:?]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_65]

kafka有手动强制分配leader的脚本:
./kafka-preferred-replica-election.sh --zookeeper  192.168.6.20:2181
这个是均衡leader在各broker上的分配的。例如每个broker上都分配10个左右leader,这样可以使broker的读写压力比较均衡。
但并不能解决当前问题,上面的leader还是-1。

再试一下强制分配副本脚本。
生成方案脚本:
 ./bin/kafka-reassign-partitions.sh --topics-to-move-json-file topics-to-move.json --broker-list "0,2" --generate --zookeeper localhost:2181

topics-to-move.json:
{
  "topics":
     [
       {
         "topic": "pc_gktp"
       }
     ],     
     "version":1
}
生成的方案(gtp_reassign.json):
{"version":1,"partitions":[{"topic":"pc_gktp","partition":0,"replicas":[2,0],"log_dirs":["any","any"]}]}
 执行强制分配副本脚本
 ./bin/kafka-reassign-partitions.sh --reassignment-json-file gtp_reassign.json --execute --zookeeper localhost:2181
 
 确认执行状态:
 ./bin/kafka-reassign-partitions.sh --reassignment-json-file gtp_reassign.json --verify --zookeeper localhost:2181
 
 现象:
 Reassignment of partition [pc_gktp, 1] is still in process
 Reassignment一直在执行。
 "./kafka-topics.sh --zookeeper  192.168.6.20:2181  --describe --unavailable-partitions"结果中可以看到:
Topic: pc_gtp   Partition: 0    Leader: -1      Replicas: 2,0,1 Isr: 1
Replicas多了一个。
zookeeper的/admin下有一个reassign_partitions节点。

原因:
查看这个帖子:
https://community.hortonworks.com/content/supportkb/189958/the-kafka-topic-partitions-do-not-re-balance-itsel.html?tdsourcetag=s_pcqq_aiomsg
里面说得比较清楚
The Kafka topic partitions do not re-balance itself if one of Kafka broker in ISR is down and remains under-replicated
因为“partition 1”在Isr中,正在复制状态,但是所在broker宕了。

解决办法:
参见这个帖子
https://stackoverflow.com/questions/45430936/kafka-how-to-remove-broker-from-replica-set
就是新建一个kafka broker,id跟宕掉的一样。

我把关掉的broker的配置文件改了一下,把数据目录换了位置。然后重新启动。
执行[root@s20 bin]# ./kafka-topics.sh --zookeeper  192.168.6.20:2181  --describe --unavailable-partitions
已经没有获取不到的partition了。

问题解决了吗?
发现192.168.6.20上的kafka起不来。日志显示:
[2019-05-27 19:50:06,466] ERROR [ReplicaFetcher replicaId=0, leaderId=1, fetcherId=0] Exiting because log truncation is not allowed for partition pc_exp_skmpp-1, current leader's latest offset 0 is less than replica's latest offset 946 (kafka.server.ReplicaFetcherThread)
原因:
https://stackoverflow.com/questions/52036973/kafka-halting-because-log-truncation-is-not-allowed-for-topic-error-shuttng-down
pc_exp_skmpp-1 partiton的leader的offset比副本的offset小。这是不正常的,原因应该是原来的leader因为宕机发生了切换,未完全复制的副本变成了leader.据说这个问题在0.11.0版已经解决了。但这儿又出现了。
解决办法:
上面贴子已经说了:
所有kafka配置文件中添加“unclean.leader.election.enable=true”,然后重起所有的broker。
问题:
有可能丢失数据。
修改后问题确实解决了。

下面这个帖子说了一个宕机恢复的实验,情况稍微简单一点,也能说明点问题:
https://blog.csdn.net/ashic/article/details/87876824

总结一下恢复过程
1 新建一个broker, id跟宕掉的broker一样。启动该broker
2 通过下面脚本查看恢复状态
./kafka-topics.sh --zookeeper  192.168.6.20:2181  --describe --unavailable-partitions
3 确认下所有broker启动正常,如果有因为leader的offset滞后导致不能启动的,需要设置
unclean.leader.election.enable=true
然后所有broker重起。
 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值