kafka 集羣運維和使用

最近在維護kafka集羣,遇到了很多問題都需要記錄下:

集羣信息:12臺服務器,每臺機子12塊盤每塊1.8T,其中6臺做RAID,6臺使用12塊盤,64G內存,CPU24核,萬兆網卡。集羣每天寫入的消息量能到每天33億條消息,消費暫時還沒有統計(通過ZK消費的消息量大概每天100億,還有很大一部分走的SimpleConsumer沒有統計)。

topic數量(截止2014-11-09):

topic  --  205個

集羣數據存儲量(截止2014-11-09):  --  總共容量252T,已經使用39.4T,已用百分比15.63%

16634 -- 4.2T
16781 -- 4.4T
16782 -- 4.8T
16783 -- 3.5T
16784 -- 3.5T
16785 -- 4.2T
18081 -- 225+181+214+205+214+208+199+194+371+199+192+184 = 2586G
18082 -- 226+187+202+212+209+209+193+178+241+291+179+183 = 2510G
18083 -- 207+200+214+210+208+207+182+181+212+189+183+187 = 2380G
18084 -- 207+187+211+211+209+213+180+188+370+191+193+184 = 2544G
18085 -- 213+194+207+207+219+210+180+186+199+192+190+200 = 2397G
18086 -- 222+194+215+202+216+211+198+191+188+197+184+183 = 2401G(12塊盤每塊1.8T的容量,這裏G爲單位)

網卡的上下行流量(截止2014-11-09):

16634,16785 --- 50mb/s左右
16784  --- 35mb/s左右
16783,16782,16781  --- 30mb/s左右
18081,18082,18083,18084,18085,18086  -- 20mb/s左右

最近9天寫入kafka集羣的消息情況如圖(截止2014-11-09,臨近雙11流量的消息量翻倍):


1.  kafka 的topic 級別的配置修改

       創建topic 的時候可以指定topic 的自己的相關配置與集羣配置衝突,優先走topic自己的配置,未配置的走集羣配置

./kafka-topics.sh --zookeeper 127.0.0.1:2181/kafka_2_10 --create --topic avrotest1 --partitions 1 --replication-factor 1 --config max.message.bytes=64000 --config flush.messages=1

       修改其中的配置或者增加(注意:如果配置不是Topic_level的會報錯--Error while executing topic command requirement failed: Unknown configuration "retention.hours")

./kafka-topics.sh --zookeeper 127.0.0.1:2181/kafka_2_10 --alter --topic avrotest1 --config retention.ms=128
       刪除某個topic的配置信息

./kafka-topics.sh --zookeeper 127.0.0.1:2181/kafka_2_10 --alter --topic avrotest1 --deleteConfig max.message.bytes

       retention.ms=43200000  ---- topic數據保存的時間,超過這個時間則刪除 以毫秒爲單位,其他參數可見官方配置信息說明

2.   kafka集羣發送時間長,集羣機子網卡上下行流量很不均衡,有些broker寫數據的時間很長,經過測試修改發送ack爲一份確認會快很多,也就是kafka的多broker之間拉取數據備份耗時較長,採取如下措施:

      1) num.replica.fetchers=4  增加複製的線程數,默認爲1  (broker配置)
      2)replica.fetch.max.bytes=2097152  每次拉取消息的大小上線 (broker配置)
      3)auto.leader.rebalance.enable=true
           leader.imbalance.per.broker.percentage=10
           leader.imbalance.check.interval.seconds=3600   自動均衡leader 每小時做一次(broker配置)

3.  手動指定分配topic的replica

     編寫需要分配的topic,partion和replica 的關係json,例如:(寫入到test_reassignment.json)

     {"version":1,"partitions":[{"topic":"mine-topic","partition":0,"replicas":[16784,16785]},{"topic":"mine-topic","partition":1,"replicas":[16785,16634]}]}

     按照指定的分配規則執行

  ./kafka-reassign-partitions.sh --zookeeper 127.0.0.1:2181/kafka_2_10 --reassignment-json-file test_reassignment.json --execute

     可以查看執行進度

 ./kafka-reassign-partitions.sh --zookeeper 127.0.0.1:2181/kafka_2_10 --reassignment-json-file test_reassignment.json --verify

4.  kafka字段分配到指定topic到指定的broker上

     編寫topics-to-move.json

{"topics": [{"topic": "foo1"},
       {"topic": "foo2"}],
 "version":1
}
     指定需要分配到的brokerlist 然後自動生成3中的配置json,kafka自動生成的json中replica會分佈在指定的broker list上

./kafka-reassign-partitions.sh --zookeeper localhost:2181 --topics-to-move-json-file topics-to-move.json --broker-list "5,6" --generate 
     將配置信息複製到json文件中按照3中的步驟就可以執行了

執行前---

{"version":1,
 "partitions":[{"topic":"foo1","partition":2,"replicas":[1,2]},
               {"topic":"foo1","partition":0,"replicas":[3,4]},
               {"topic":"foo2","partition":2,"replicas":[1,2]},
               {"topic":"foo2","partition":0,"replicas":[3,4]},
               {"topic":"foo1","partition":1,"replicas":[2,3]},
               {"topic":"foo2","partition":1,"replicas":[2,3]}]
}
執行後---

{"version":1,
 "partitions":[{"topic":"foo1","partition":2,"replicas":[5,6]},
               {"topic":"foo1","partition":0,"replicas":[5,6]},
               {"topic":"foo2","partition":2,"replicas":[5,6]},
               {"topic":"foo2","partition":0,"replicas":[5,6]},
               {"topic":"foo1","partition":1,"replicas":[5,6]},
               {"topic":"foo2","partition":1,"replicas":[5,6]}]
}

5.  手動Balancing leadership 

     當topic有多個分區的時候,leader爲replica list中最前面的那個broker,這個掛掉的時候leader會切換到其他的replaca中,這個時候可以kafka集羣恢復leader,恢復副本運行

./kafka-preferred-replica-election.sh --zookeeper zk_host:port/chroot
     可以修改broker config來自動配置(執行時間間隔也可以設置見其他文章)

auto.leader.rebalance.enable=true

6.   遇到問題-kafka集羣發送消息時間要很長甚者要到5秒以上,後臺有16784Broker會不斷自己重新向zk註冊Broker(斷掉所有鏈接,重新註冊再把所有topic都rollback回來,網卡上下行一直上不來,鏈接數也很少)。經過查看各種監控信息,找到了源頭並處理了這次事故:
xxx-topic 在前一天17:50 -- 第二天12:00之間發送數據,發送數據量46億條消息
Topic: xxx-topic  分區:3  備份:3

Partition: 0	Leader: 16634	Replicas: 16634,16781,16782	Isr: 16634,16781,16782
Partition: 1	Leader: 16783	Replicas: 16783,18081,18082	Isr: 18081,18082,16783
Partition: 2	Leader: 16784	Replicas: 16784,18082,18083	Isr: 18082,18083,16784
在18:16左右就開始時斷時續的報錯,從16784拉取leader消息鏈接超時,同時也會有消息繼續寫入到18082這個broker(後續切換leader爲18082),18082broker的網卡的上下行流量飆升到90Mb/s(應該是接近瓶頸),鏈接這個broker的topic發送數據會報錯發多次不能成功發送,發送成功時發送的時間也很漲很高.18083broker在次期間網卡流量也在40-70mb/s之間波動。於此同時16784broker後臺在第二天看日誌的時候會不停的重新在zk註冊broker,會先停掉broker的鏈接和複製線程,然後其他相關topic的備份都會去掉這個broker然後等重新註冊好broker之後再Expanding ISR將此broker加入進去,然後不停的做此操作,16784這個broker網卡上下行由於一直在重新註冊broker處於20-50mb/s波動,在此期間16784broker重啓之後沒有起作用還是在重新註冊broker,16784的平時網卡就在40-50Mb/s左右。在開始發送的時候也就是18:20之前數據leader應該是在16784,這個時間段16784的網卡上下行在105Mb/s左右,過了這個段時間這個xxx-topic的leader切到了18082上,18082的網卡開始飆升,且一直維持在90mb/s的狀態。
注:Partition 0 和 Partition: 1 的量都不大,Partition 2的量很大,此情況猜測每條消息的key是一樣的(後續經過詢問證實用了固定的key)。
分析處理:kafka集羣單個broker寫入消息的量太大(網卡和存儲)會影響很大,一定要把數據量大的topic創建多個分區(根據topic的量大小來估算分區數量)分攤到不同的broker上,切發送時候的分區方法要設置均勻保證每個分區的量都差不多,關閉自動創建topic的功能,防止未知的topic出現這種問題。
16784Broker日誌(會不斷重複,truncate topic數據 rollback數據日誌等全都省略):
[2014-11-07 10:12:01,495] INFO re-registering broker info in ZK for broker 16784 (kafka.server.KafkaHealthcheck)
[2014-11-07 10:12:01,667] INFO Registered broker 16784 at path /brokers/ids/16784 with address 172.22.167.84:9092. (kafka.utils.ZkUtils$)
[2014-11-07 10:12:01,668] INFO done re-registering broker (kafka.server.KafkaHealthcheck)
[2014-11-07 10:12:01,669] INFO Subscribing to /brokers/topics path to watch for new topics (kafka.server.KafkaHealthcheck)
鏈接超時報錯信息:
[2014-11-06 18:16:47,184] ERROR [ReplicaFetcherThread-3-16784], Error in fetch Name: FetchRequest; Version: 0; CorrelationId: 2242020; ClientId: ReplicaFetcherThread-3-16784; ReplicaId: 18082; MaxWait: 500 ms; MinBytes: 1 bytes; RequestInfo: [xxx-topic,2] -> PartitionFetchInfo(335480909,2097152) (kafka.server.ReplicaFetcherThread)
java.net.SocketTimeoutException
    at sun.nio.ch.SocketAdaptor$SocketInputStream.read(SocketAdaptor.java:229)
    at sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:103)
    at java.nio.channels.Channels$ReadableByteChannelImpl.read(Channels.java:385)
    at kafka.utils.Utils$.read(Utils.scala:375)
    at kafka.network.BoundedByteBufferReceive.readFrom(BoundedByteBufferReceive.scala:54)
    at kafka.network.Receive$class.readCompletely(Transmission.scala:56)
    at kafka.network.BoundedByteBufferReceive.readCompletely(BoundedByteBufferReceive.scala:29)
    at kafka.network.BlockingChannel.receive(BlockingChannel.scala:100)
    at kafka.consumer.SimpleConsumer.liftedTree1$1(SimpleConsumer.scala:81)
    at kafka.consumer.SimpleConsumer.kafka$consumer$SimpleConsumer$$sendRequest(SimpleConsumer.scala:71)
    at kafka.consumer.SimpleConsumer$$anonfun$fetch$1$$anonfun$apply$mcV$sp$1.apply$mcV$sp(SimpleConsumer.scala:109)
    at kafka.consumer.SimpleConsumer$$anonfun$fetch$1$$anonfun$apply$mcV$sp$1.apply(SimpleConsumer.scala:109)
    at kafka.consumer.SimpleConsumer$$anonfun$fetch$1$$anonfun$apply$mcV$sp$1.apply(SimpleConsumer.scala:109)
    at kafka.metrics.KafkaTimer.time(KafkaTimer.scala:33)
    at kafka.consumer.SimpleConsumer$$anonfun$fetch$1.apply$mcV$sp(SimpleConsumer.scala:108)
    at kafka.consumer.SimpleConsumer$$anonfun$fetch$1.apply(SimpleConsumer.scala:108)
    at kafka.consumer.SimpleConsumer$$anonfun$fetch$1.apply(SimpleConsumer.scala:108)
    at kafka.metrics.KafkaTimer.time(KafkaTimer.scala:33)
    at kafka.consumer.SimpleConsumer.fetch(SimpleConsumer.scala:107)
    at kafka.server.AbstractFetcherThread.processFetchRequest(AbstractFetcherThread.scala:96)
    at kafka.server.AbstractFetcherThread.doWork(AbstractFetcherThread.scala:88)
    at kafka.utils.ShutdownableThread.run(ShutdownableThread.scala:51)
[2014-11-06 18:16:47,196] WARN Reconnect due to socket error: null (kafka.consumer.SimpleConsumer)

7.  手動Balancing leadership 時需要改變Replicas順序,或者添加其他Replicas,可以先用上述4的方法改變Replicas 中broker的順序或者添加刪除broker,然後在用上述5中方法進行手動balance(注意:kafka-preferred-replica-election.sh 執行這個會將topic 的某個partition的leader 選舉爲Replicas中最前面的那個)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章