查看kafka數(shù)據(jù)文件內(nèi)容
在使用kafka的過程中有時候需要我們查看產(chǎn)生的消息的信息,這些都被記錄在kafka的log文件中。由于log文件的特殊格式,需要通過kafka提供的工具來查看。
./bin/kafka-run-class.sh kafka.tools.DumpLogSegments --files /tmp/kafka-logs/*/000**.log --print-data-log {查看消息內(nèi)容}
高可用副本機制
在kafka0.8版本前,并沒有提供這種High Availablity機制,也就是說一旦一個或者多個broker宕機,則在這期間內(nèi)所有的partition都無法繼續(xù)提供服務(wù)。如果broker無法再恢復(fù),則上面的數(shù)據(jù)就會丟失。所以在0.8版本以后引入了High Availablity機制。
關(guān)于leader election
在kafka引入replication機制以后,同一個partition會有多個Replica。那么在這些replication之間需要選出一個Leader,Producer或者Consumer只與這個Leader進(jìn)行交互,其他的Replica作為Follower從leader中復(fù)制數(shù)據(jù)(因為需要保證一個Partition中的多個Replica之間的數(shù)據(jù)一致性,其中一個Replica宕機以后其他的Replica必須要能繼續(xù)提供服務(wù)且不能造成數(shù)據(jù)重復(fù)和數(shù)據(jù)丟失)。 如果沒有l(wèi)eader,所有的Replica都可以同時讀寫數(shù)據(jù),那么就需要保證多個Replica之間互相同步數(shù)據(jù),數(shù)據(jù)一致性和有序性就很難保證,同時也增加了Replication實現(xiàn)的復(fù)雜性和出錯的概率。在引入leader以后,leader負(fù)責(zé)數(shù)據(jù)讀寫,follower只向leader順序fetch數(shù)據(jù),簡單而且高效。
如何將所有的Replica均勻分布到整個集群
為了更好的做到負(fù)載均衡,kafka盡量會把所有的partition均勻分配到整個集群上。如果所有的replica都在同一個broker上,那么一旦broker宕機所有的Replica都無法工作。kafka分配Replica的算法
1.把所有的Broker(n)和待分配的Partition排序
2.把第i個partition分配到 (i mod n)個broker上
3.把第i個partition的第j個Replica分配到 ( (i+j) mod n) 個broker上
如何處理所有的Replica不工作的情況
在ISR中至少有一個follower時,Kafka可以確保已經(jīng)commit的數(shù)據(jù)不丟失,但如果某個Partition的所有Replica都宕機了,就無法保證數(shù)據(jù)不丟失了。
1.等待ISR中的任一個Replica“活”過來,并且選它作為Leader
2.選擇第一個“活”過來的Replica(不一定是ISR中的)作為Leader
這就需要在可用性和一致性當(dāng)中作出一個簡單的折衷。
如果一定要等待ISR中的Replica“活”過來,那不可用的時間就可能會相對較長。而且如果ISR中的所有Replica都無法“活”過來了,或者數(shù)據(jù)都丟失了,這個Partition將永遠(yuǎn)不可用。
選擇第一個“活”過來的Replica作為Leader,而這個Replica不是ISR中的Replica,那即使它并不保證已經(jīng)包含了所有已commit的消息,它也會成為Leader而作為consumer的數(shù)據(jù)源。
Kafka0.8.*使用了第二種方式。Kafka支持用戶通過配置選擇這兩種方式中的一種,從而根據(jù)不同的使用場景選擇高可用性還是強一致性。
文件存儲機制
存儲機制
在kafka文件存儲中,同一個topic下有多個不同的partition,每個partition為一個目錄,partition的名稱規(guī)則為:topic名稱+有序序號,第一個序號從0開始,最大的序號為partition數(shù)量減1,partition是實際物理上的概念,而topic是邏輯上的概念partition還可以細(xì)分為segment,這個segment是什么呢? 假設(shè)kafka以partition為最小存儲單位,那么我們可以想象當(dāng)kafka producer不斷發(fā)送消息,必然會引起partition文件的無線擴張,這樣對于消息文件的維護以及被消費的消息的清理帶來非常大的挑戰(zhàn),所以kafka 以segment為單位又把partition進(jìn)行細(xì)分。每個partition相當(dāng)于一個巨型文件被平均分配到多個大小相等的segment數(shù)據(jù)文件中(每個segment文件中的消息不一定相等),這種特性方便已經(jīng)被消費的消息的清理,提高磁盤的利用率。
segment file組成:由2大部分組成,分別為index file和data file,此2個文件一一對應(yīng),成對出現(xiàn),后綴".index"和“.log”分別表示為segment索引文件、數(shù)據(jù)文件.
segment文件命名規(guī)則:partion全局的第一個segment從0開始,后續(xù)每個segment文件名為上一個segment文件最后一條消息的offset值。數(shù)值最大為64位long大小,19位數(shù)字字符長度,沒有數(shù)字用0填充
消息確認(rèn)的幾種方式
自動提交
手動提交
手動異步提交
consumer. commitASync() //手動異步ack
手動同步提交
consumer. commitSync() //手動異步ack
消息的消費原理
之前Kafka存在的一個非常大的性能隱患就是利用ZK來記錄各個Consumer Group的消費進(jìn)度(offset)。當(dāng)然JVM Client幫我們自動做了這些事情,但是Consumer需要和ZK頻繁交互,而利用ZK Client API對ZK頻繁寫入是一個低效的操作,并且從水平擴展性上來講也存在問題。所以ZK抖一抖,集群吞吐量就跟著一起抖,嚴(yán)重的時候簡直抖的停不下來。
新版Kafka已推薦將consumer的位移信息保存在Kafka內(nèi)部的topic中,即__consumer_offsets topic。通過以下操作來看看__consumer_offsets_topic是怎么存儲消費進(jìn)度的,__consumer_offsets_topic默認(rèn)有50個分區(qū)
獲得consumer group的位移信息
bin/kafka-simple-consumer-shell.sh --topic __consumer_offsets --partition 15 -broker-list 192.168.11.xxx:9092,192.168.11.xxx:9092,192.168.11.xxx:9092 --formatter kafka.coordinator.group.GroupMetadataManager\$OffsetsMessageFormatter
kafka的分區(qū)分配策略
在kafka中每個topic一般都會有很多個partitions。為了提高消息的消費速度,我們可能會啟動多個consumer去消費; 同時,kafka存在consumer group的概念,也就是group.id一樣的consumer,這些consumer屬于一個consumer group,組內(nèi)的所有消費者協(xié)調(diào)在一起來消費消費訂閱主題的所有分區(qū)。當(dāng)然每一個分區(qū)只能由同一個消費組內(nèi)的consumer來消費,那么同一個consumer group里面的consumer是怎么去分配該消費哪個分區(qū)里的數(shù)據(jù),這個就設(shè)計到了kafka內(nèi)部分區(qū)分配策略(Partition Assignment Strategy)
在 Kafka 內(nèi)部存在兩種默認(rèn)的分區(qū)分配策略:Range(默認(rèn)) 和 RoundRobin。通過:partition.assignment.strategy指定
consumer rebalance
當(dāng)以下事件發(fā)生時,Kafka 將會進(jìn)行一次分區(qū)分配:
1.同一個consumer group內(nèi)新增了消費者
2.消費者離開當(dāng)前所屬的consumer group,包括shuts down 或crashes
3.訂閱的主題新增分區(qū)(分區(qū)數(shù)量發(fā)生變化)
4.消費者主動取消對某個topic的訂閱
5.也就是說,把分區(qū)的所有權(quán)從一個消費者移到另外一個消費者上,這個是kafka consumer 的rebalance機制。如何rebalance就涉及到前面說的分區(qū)分配策略。