前言
說(shuō)這幾個(gè)概念之前呢逐抑?先說(shuō)幾個(gè)問(wèn)題
1.kakfa是什么?
Kafka 是一個(gè)分布式的基于發(fā)布/訂閱模式的消息隊(duì)列(Message Queue)屹蚊,主要應(yīng)用與大數(shù)據(jù)"實(shí)時(shí)"處理領(lǐng)域
2.kafka有什么作用
Kafka 本質(zhì)上是一個(gè) MQ(Message Queue)厕氨,使用消息隊(duì)列的好處?(此處是面試題)
- 解耦:允許我們獨(dú)立的擴(kuò)展或修改隊(duì)列兩邊的處理過(guò)程。
- 可恢復(fù)性:即使一個(gè)處理消息的進(jìn)程掛掉汹粤,加入隊(duì)列中的消息仍然可以在系統(tǒng)恢復(fù)后被處理命斧。
- 緩沖:有助于解決生產(chǎn)消息和消費(fèi)消息的處理速度不一致的情況。
- 靈活性&峰值處理能力:不會(huì)因?yàn)橥话l(fā)的超負(fù)荷的請(qǐng)求而完全崩潰嘱兼,消息隊(duì)列能夠使關(guān)鍵組件頂住突發(fā)的訪問(wèn)壓力(削峰)国葬。
- 異步通信:消息隊(duì)列允許用戶把消息放入隊(duì)列但不立即處理它。
1. producer - 生產(chǎn)者
顧名思義芹壕,生產(chǎn)者汇四,生產(chǎn)消息的那個(gè)家伙。
在準(zhǔn)確點(diǎn)形容就是:向 Kafka Broker 發(fā)消息的客戶端踢涌。
既然發(fā)送消息了通孽,那么消息就有可能存在丟失,比如消息發(fā)送失敗了睁壁。
那怎么預(yù)防這類事情發(fā)生呢背苦?
Kafka 在生產(chǎn)者上有一個(gè)可選的參數(shù) ack,該參數(shù)指定了必須要有多少個(gè)分區(qū)副本收到消息潘明,生產(chǎn)者才會(huì)認(rèn)為消息寫(xiě)入成功:
acks=0 :消息發(fā)送出去就認(rèn)為已經(jīng)成功了行剂,不會(huì)等待任何來(lái)自服務(wù)器的響應(yīng)
acks=1 : 只要集群的首領(lǐng)節(jié)點(diǎn)收到消息,生產(chǎn)者就會(huì)收到一個(gè)來(lái)自服務(wù)器成功響應(yīng)
acks=all :只有當(dāng)所有參與復(fù)制的節(jié)點(diǎn)全部收到消息時(shí)钳降,生產(chǎn)者才會(huì)收到一個(gè)來(lái)自服務(wù)器的成功響應(yīng)
2. broker - 消息服務(wù)器
【這里只是舉了一個(gè)消費(fèi)者采用啦的模式厚宰,當(dāng)然還有推的模式】
從這張圖來(lái)理解broker的定位會(huì)更好記一點(diǎn),可以理解為牲阁,生產(chǎn)者把消息給broker固阁,consumer從broker拉取消息進(jìn)行消費(fèi)(數(shù)據(jù)處理)
來(lái)看下百科的解釋
它的主要作用是在ZooKeeper 的幫助下管理和協(xié)調(diào)整個(gè)Kafka 集群。 集群中任意一臺(tái)Broker 都能充當(dāng)控制器的角色城菊,但是在運(yùn)行過(guò)程中备燃,只能有一個(gè)Broker 成為控制器,來(lái)執(zhí)行管理和協(xié)調(diào)的職責(zé)凌唬。
這么說(shuō)來(lái)并齐,broker就不是一臺(tái)機(jī)器了,而是一個(gè)集群(類似于redis集群,同樣有l(wèi)eader的選舉和存活檢測(cè)况褪,不過(guò)這個(gè)就由zookeeper來(lái)幫助了撕贞,畢竟人家才是背后的大哥)
(記住這個(gè)圖有點(diǎn)問(wèn)題,后面會(huì)改正,看下面這句話就知道圖不是很形象了)
那么實(shí)際的關(guān)系是:
一臺(tái) Kafka 機(jī)器就是一個(gè) Broker测垛。一個(gè)集群由多個(gè) Broker 組成捏膨。一個(gè) Broker 可以容納多個(gè) Topic。
這樣看起來(lái)的話食侮,當(dāng)producer將消息投遞到broker的時(shí)候号涯,會(huì)存在一個(gè)很嚴(yán)重的問(wèn)題,就是消息丟失锯七。
既然存在那么如何解決呢链快?
2.1 消息在broker丟失了怎么辦
腦補(bǔ)中。眉尸。
Broker丟失消息是由于Kafka本身的原因造成的域蜗,kafka為了得到更高的性能和吞吐量,將數(shù)據(jù)異步批量的存儲(chǔ)在磁盤(pán)中噪猾。消息的刷盤(pán)過(guò)程霉祸,為了提高性能,減少刷盤(pán)次數(shù)畏妖,kafka采用了批量刷盤(pán)的做法脉执。即疼阔,按照一定的消息量戒劫,和時(shí)間間隔進(jìn)行刷盤(pán)。這種機(jī)制也是由于linux操作系統(tǒng)決定的婆廊。將數(shù)據(jù)存儲(chǔ)到linux操作系統(tǒng)種迅细,會(huì)先存儲(chǔ)到頁(yè)緩存(Page cache)中,按照時(shí)間或者其他條件進(jìn)行刷盤(pán)(從page cache到file)淘邻,或者通過(guò)fsync命令強(qiáng)制刷盤(pán)茵典。數(shù)據(jù)在page cache中時(shí),如果系統(tǒng)掛掉宾舅,數(shù)據(jù)會(huì)丟失统阿。
刷盤(pán)觸發(fā)條件有三:
主動(dòng)調(diào)用sync或fsync函數(shù)
可用內(nèi)存低于閥值
dirty data時(shí)間達(dá)到閥值。dirty是pagecache的一個(gè)標(biāo)識(shí)位筹我,當(dāng)有數(shù)據(jù)寫(xiě)入到pageCache時(shí)扶平,pagecache被標(biāo)注為dirty,數(shù)據(jù)刷盤(pán)以后蔬蕊,dirty標(biāo)志清除结澄。
Broker配置刷盤(pán)機(jī)制,是通過(guò)調(diào)用fsync函數(shù)接管了刷盤(pán)動(dòng)作。從單個(gè)Broker來(lái)看麻献,pageCache的數(shù)據(jù)會(huì)丟失们妥。
也就是說(shuō),理論上勉吻,要完全讓kafka保證單個(gè)broker不丟失消息是做不到的监婶,只能通過(guò)調(diào)整刷盤(pán)機(jī)制的參數(shù)緩解該情況。比如齿桃,減少刷盤(pán)間隔压储,減少刷盤(pán)數(shù)據(jù)量大小。時(shí)間越短源譬,性能越差集惋,可靠性越好(盡可能可靠)。這是一個(gè)選擇題踩娘。
為了解決該問(wèn)題刮刑,kafka通過(guò)producer和broker協(xié)同處理單個(gè)broker丟失參數(shù)的情況。一旦producer發(fā)現(xiàn)broker消息丟失养渴,即可自動(dòng)進(jìn)行retry雷绢。除非retry次數(shù)超過(guò)閥值(可配置),消息才會(huì)丟失理卑。此時(shí)需要生產(chǎn)者客戶端手動(dòng)處理該情況翘紊。那么producer是如何檢測(cè)到數(shù)據(jù)丟失的呢?是通過(guò)ack機(jī)制藐唠,類似于http的三次握手的方式帆疟。
3. topic - 消息主題
topic是消息的邏輯分類,可以看做是一個(gè)消息類別的名稱宇立,同類消息發(fā)送到同一個(gè)Topic下面踪宠。
舉個(gè)荔枝,訂單消息妈嘹,商品的信息柳琢,2個(gè)類型,他們的消息內(nèi)容润脸,消息格式可能會(huì)存在差異性柬脸,并且都有各自的生產(chǎn)者和消費(fèi)者。
如果按照一個(gè)消息類型建立kafka系統(tǒng)毙驯,那么得搭建多少個(gè)系統(tǒng)能滿足一個(gè)龐大的業(yè)務(wù)系統(tǒng)呢倒堕?
所以就有了Topic這個(gè)東西-邏輯分類,假如一個(gè)消息類型放到一個(gè)Topic中就合理了尔苦。
所以在生產(chǎn)消息時(shí)涩馆,就需要指定Topic了行施。這么想來(lái)是不是就合理了呢。
好了魂那,到了總結(jié)時(shí)間了
1.消息生產(chǎn)時(shí)需要指定生產(chǎn)到哪個(gè)topic
2.每個(gè)topic就是一類消息
3.消費(fèi)時(shí)需要指定消費(fèi)那個(gè)topic數(shù)據(jù)
既然每個(gè)topic消息是一種類型蛾号,那么相信你面試過(guò)程中聽(tīng)過(guò)一個(gè)非常經(jīng)典的面試題:kakfa如何保證順序消費(fèi)呢?
沒(méi)錯(cuò)涯雅,單一partition內(nèi)的消息天然有序的
假如有人問(wèn)怎么保證有序鲜结,這下知道怎么回了吧,那么如何保證不同topic之間的順序呢活逆,這個(gè)得從自己的業(yè)務(wù)出發(fā)精刷,植入相應(yīng)的數(shù)據(jù)消費(fèi)序號(hào),或者消費(fèi)者拿到數(shù)據(jù)后再放到自己的mq中消費(fèi)了蔗候。
好了怒允,結(jié)合上述,畫(huà)出圖吧
4.patition - 主題內(nèi)分區(qū)
4.1定義
partition是個(gè)什么東西呢锈遥?
既然有topic了纫事,分類都有了,還缺什么嗎所灸?
topic是邏輯的概念丽惶,partition是物理的概念。 啥是物理概念爬立,就是物理上進(jìn)行分離钾唬,分布在不同的實(shí)體機(jī)器上。
引用知乎上一個(gè)非常合適的荔枝來(lái)說(shuō)明就在合適不過(guò)了
Kafka的設(shè)計(jì)也是源自生活侠驯,好比是為公路運(yùn)輸抡秆,不同的起始點(diǎn)和目的地需要修不同高速公路(主題topic)。高速公路上可以提供多條車道(分區(qū)partition)陵霉,流量大的公路多修幾條車道保證暢通琅轧,流量小的公路少修幾條車道避免浪費(fèi)伍绳。收費(fèi)站好比消費(fèi)者踊挠,車多的時(shí)候多開(kāi)幾個(gè)一起收費(fèi)避免堵在路上,車少的時(shí)候開(kāi)幾個(gè)讓汽車并道就好了冲杀。
說(shuō)直白點(diǎn)呢效床,不同的公路就是topic, 公路上存在多條車道权谁,每條車道就是分區(qū)partition
4.2 作用
如果沒(méi)有分區(qū)剩檀,一個(gè)topic對(duì)應(yīng)的消息集在分布式集群服務(wù)組中,就會(huì)分布不均勻旺芽,即可能導(dǎo)致某臺(tái)服務(wù)器A記錄當(dāng)前topic的消息集很多沪猴,若此topic的消息壓力很大的情況下辐啄,服務(wù)器A就可能導(dǎo)致壓力很大,吞吐也容易導(dǎo)致瓶頸运嗜。
所以很明顯partition的作用就來(lái)了:通過(guò)多分區(qū)實(shí)現(xiàn)負(fù)載均衡的效果壶辜,提高kafka訪問(wèn)吞吐率。
Topic 是一個(gè)邏輯概念担租,Partition 是最小的存儲(chǔ)單元砸民,掌握著一個(gè) Topic 的部分?jǐn)?shù)據(jù)。每個(gè) Partition 都是一個(gè)單獨(dú)的 log 文件奋救;
借用下知乎圖
那么patition和topic的關(guān)系就是
4.3 如何寫(xiě)入partition岭参?
消息以追加的方式寫(xiě)入分區(qū),然后以先入先出的順序讀取尝艘。Kafka 通過(guò)分區(qū)來(lái)實(shí)現(xiàn)數(shù)據(jù)的冗余和伸縮性演侯,分區(qū)可以分布在不同的服務(wù)器上,這意味著一個(gè) Topic 可以橫跨多個(gè)服務(wù)器背亥,以提供比單個(gè)服務(wù)器更強(qiáng)大的性能蚌本。
具體的方式有3種:
- 采用輪訓(xùn)的方式寫(xiě)入到每個(gè)partition中(默認(rèn)采用的方式)
- producer指定寫(xiě)入到哪個(gè)partition中
- 自定義寫(xiě)入
producer指定寫(xiě)入到哪個(gè)partition中或者自定義寫(xiě)入有一個(gè)最好的利用點(diǎn),就是不至于熱點(diǎn)數(shù)據(jù)全部到一個(gè)partition中隘梨,導(dǎo)致數(shù)據(jù)嚴(yán)重傾斜程癌。
5. groups - 消費(fèi)組
消費(fèi)者組內(nèi)每個(gè)消費(fèi)者負(fù)責(zé)消費(fèi)不同分區(qū)的數(shù)據(jù),提高消費(fèi)能力轴猎。一個(gè)分區(qū)只能由組內(nèi)一個(gè)消費(fèi)者消費(fèi)嵌莉,消費(fèi)者組之間互不影響。所有的消費(fèi)者都屬于某個(gè)消費(fèi)者組捻脖,即消費(fèi)者組是邏輯上的一個(gè)訂閱者锐峭。
那么消費(fèi)組和消費(fèi)者的關(guān)系就是這樣子了
6.概念說(shuō)完了,那么如何消費(fèi)數(shù)據(jù)呢可婶?
6.1 pull(拉)模式
由消費(fèi)者沿癞,主動(dòng)從 broker 中讀取數(shù)據(jù)
pull 模式可以根據(jù) consumer 的消費(fèi)能力以適當(dāng)?shù)乃俾氏M(fèi)消息。
優(yōu)點(diǎn):主動(dòng)權(quán)在消費(fèi)者手里矛渴,想什么時(shí)候要就要椎扬,類似于現(xiàn)在bsp+緩存池 數(shù)據(jù)進(jìn)專工的模型
缺點(diǎn):如果 kafka 沒(méi)有數(shù)據(jù),消費(fèi)者可能會(huì)陷入循環(huán)中
針對(duì)這一點(diǎn)具温,Kafka 的消費(fèi)者在消費(fèi)數(shù)據(jù)時(shí)會(huì)傳入一個(gè)時(shí)長(zhǎng)參數(shù) timeout蚕涤,如果當(dāng)前沒(méi)有數(shù)據(jù)可供消費(fèi),consumer 會(huì)等待一段時(shí)間之后再返回铣猩,這段時(shí)長(zhǎng)即為 timeout
6.2 push (推)模式
消息有broker來(lái)決定揖铜,決定發(fā)送的效率。
它的目標(biāo)是盡可能以最快速度傳遞消息达皿,但是這樣很容易造成 consumer 來(lái)不及處理消息天吓,典型的表現(xiàn)就是拒絕服務(wù)以及網(wǎng)絡(luò)擁塞贿肩。
類似于目前bsp多數(shù)的干預(yù)模式,不管下游要不要龄寞,盲推尸曼,但是不同于kfk推模式的在于,bsp架構(gòu)是有自我熔斷與限流的萄焦,一方面也是防止了那種大批量數(shù)據(jù)推入下游控轿,導(dǎo)致阻塞的情況
6.3 offset
由于 consumer 在消費(fèi)過(guò)程中可能會(huì)出現(xiàn)斷電宕機(jī)等故障,consumer 恢復(fù)后拂封,需要從故障前的位置的繼續(xù)消費(fèi)茬射,所以 consumer 需要實(shí)時(shí)記錄自己消費(fèi)到了哪個(gè) offset,以便故障恢復(fù)后繼續(xù)消費(fèi)冒签。
group + topic + partition(GTP) 才能確定一個(gè) offset在抛!
7.整體框架圖
- producer:消息生產(chǎn)者
- consumer:消息消費(fèi)者
- Topic:消息主題
- partition:主題內(nèi)分區(qū)
- Brokers:消息服務(wù)器
- Groups:消費(fèi)者組