kafka topic 一段时间不消费_全网最通俗易懂的 Kafka 入门
眾所周知,消息隊(duì)列的產(chǎn)品有好幾種,這里我選擇學(xué)習(xí)Kafka的原因,無他,公司在用。
我司使用的是Kafka和自研的消息隊(duì)列(Kafka和RocketMQ)改版,于是我就想學(xué)學(xué)Kafka這款消息隊(duì)列啦。本篇文章對Kafka入門,希望對大家有所幫助。
本文知識(shí)點(diǎn)提前預(yù)覽:
這篇文章花了我很長時(shí)間畫圖,目的是希望以最通俗易懂的方式帶大家入門,如果覺得不錯(cuò),希望能給我點(diǎn)個(gè)贊!
一、什么是Kafka?
首先我們得去官網(wǎng)看看是怎么介紹Kafka的:
https://kafka.apache.org/intro
在收集資料學(xué)習(xí)的時(shí)候,已經(jīng)發(fā)現(xiàn)有不少的前輩對官網(wǎng)的介紹進(jìn)行翻譯和總結(jié)了,所以我這里就不重復(fù)了,貼下地址大家自行去學(xué)習(xí)啦:
https://scala.cool/2018/03/learning-kafka-1/
https://colobu.com/2014/08/06/kafka-quickstart/
要做一個(gè)消息隊(duì)列可能要考慮到以下的問題:
使用消息隊(duì)列不可能是單機(jī)的(必然是分布式or集群)
數(shù)據(jù)寫到消息隊(duì)列,可能會(huì)存在數(shù)據(jù)丟失問題,數(shù)據(jù)在消息隊(duì)列需要持久化(磁盤?數(shù)據(jù)庫?Redis?分布式文件系統(tǒng)?)
想要保證消息(數(shù)據(jù))是有序的,怎么做?
為什么在消息隊(duì)列中重復(fù)消費(fèi)了數(shù)據(jù)
下面我以Kafka為例對這些問題進(jìn)行簡單的解答,進(jìn)而入門Kafka。
1.1 Kafka入門
眾所周知,Kafka是一個(gè)消息隊(duì)列,把消息放到隊(duì)列里邊的叫生產(chǎn)者,從隊(duì)列里邊消費(fèi)的叫消費(fèi)者。
一個(gè)消息中間件,隊(duì)列不單單只有一個(gè),我們往往會(huì)有多個(gè)隊(duì)列,而我們生產(chǎn)者和消費(fèi)者就得知道:把數(shù)據(jù)丟給哪個(gè)隊(duì)列,從哪個(gè)隊(duì)列消息。我們需要給隊(duì)列取名字,叫做topic(相當(dāng)于數(shù)據(jù)庫里邊表的概念)
現(xiàn)在我們給隊(duì)列取了名字以后,生產(chǎn)者就知道往哪個(gè)隊(duì)列丟數(shù)據(jù)了,消費(fèi)者也知道往哪個(gè)隊(duì)列拿數(shù)據(jù)了。我們可以有多個(gè)生產(chǎn)者往同一個(gè)隊(duì)列(topic)丟數(shù)據(jù),多個(gè)消費(fèi)者往同一個(gè)隊(duì)列(topic)拿數(shù)據(jù)
為了提高一個(gè)隊(duì)列(topic)的吞吐量,Kafka會(huì)把topic進(jìn)行分區(qū)(Partition)
所以,生產(chǎn)者實(shí)際上是往一個(gè)topic名為Java3y中的分區(qū)(Partition)丟數(shù)據(jù),消費(fèi)者實(shí)際上是往一個(gè)topic名為Java3y的分區(qū)(Partition)取數(shù)據(jù)
一臺(tái)Kafka服務(wù)器叫做Broker,Kafka集群就是多臺(tái)Kafka服務(wù)器:
一個(gè)topic會(huì)分為多個(gè)partition,實(shí)際上partition會(huì)分布在不同的broker中,舉個(gè)例子:
由此得知:Kafka是天然分布式的。
現(xiàn)在我們已經(jīng)知道了往topic里邊丟數(shù)據(jù),實(shí)際上這些數(shù)據(jù)會(huì)分到不同的partition上,這些partition存在不同的broker上。分布式肯定會(huì)帶來問題:“萬一其中一臺(tái)broker(Kafka服務(wù)器)出現(xiàn)網(wǎng)絡(luò)抖動(dòng)或者掛了,怎么辦?”
Kafka是這樣做的:我們數(shù)據(jù)存在不同的partition上,那kafka就把這些partition做備份。比如,現(xiàn)在我們有三個(gè)partition,分別存在三臺(tái)broker上。每個(gè)partition都會(huì)備份,這些備份散落在不同的broker上。
紅色塊的partition代表的是主分區(qū),紫色的partition塊代表的是備份分區(qū)。生產(chǎn)者往topic丟數(shù)據(jù),是與主分區(qū)交互,消費(fèi)者消費(fèi)topic的數(shù)據(jù),也是與主分區(qū)交互。
備份分區(qū)僅僅用作于備份,不做讀寫。如果某個(gè)Broker掛了,那就會(huì)選舉出其他Broker的partition來作為主分區(qū),這就實(shí)現(xiàn)了高可用。
另外值得一提的是:當(dāng)生產(chǎn)者把數(shù)據(jù)丟進(jìn)topic時(shí),我們知道是寫在partition上的,那partition是怎么將其持久化的呢?(不持久化如果Broker中途掛了,那肯定會(huì)丟數(shù)據(jù)嘛)。
Kafka是將partition的數(shù)據(jù)寫在磁盤的(消息日志),不過Kafka只允許追加寫入(順序訪問),避免緩慢的隨機(jī) I/O 操作。
Kafka也不是partition一有數(shù)據(jù)就立馬將數(shù)據(jù)寫到磁盤上,它會(huì)先緩存一部分,等到足夠多數(shù)據(jù)量或等待一定的時(shí)間再批量寫入(flush)
上面balabala地都是講生產(chǎn)者把數(shù)據(jù)丟進(jìn)topic是怎么樣的,下面來講講消費(fèi)者是怎么消費(fèi)的。既然數(shù)據(jù)是保存在partition中的,那么消費(fèi)者實(shí)際上也是從partition中取數(shù)據(jù)。
生產(chǎn)者可以有多個(gè),消費(fèi)者也可以有多個(gè)。像上面圖的情況,是一個(gè)消費(fèi)者消費(fèi)三個(gè)分區(qū)的數(shù)據(jù)。多個(gè)消費(fèi)者可以組成一個(gè)消費(fèi)者組。
本來是一個(gè)消費(fèi)者消費(fèi)三個(gè)分區(qū)的,現(xiàn)在我們有消費(fèi)者組,就可以每個(gè)消費(fèi)者去消費(fèi)一個(gè)分區(qū)(也是為了提高吞吐量)
按圖上所示的情況,這里想要說明的是:
如果消費(fèi)者組中的某個(gè)消費(fèi)者掛了,那么其中一個(gè)消費(fèi)者可能就要消費(fèi)兩個(gè)partition了
如果只有三個(gè)partition,而消費(fèi)者組有4個(gè)消費(fèi)者,那么一個(gè)消費(fèi)者會(huì)空閑
如果多加入一個(gè)消費(fèi)者組,無論是新增的消費(fèi)者組還是原本的消費(fèi)者組,都能消費(fèi)topic的全部數(shù)據(jù)。(消費(fèi)者組之間從邏輯上它們是獨(dú)立的)
前面講解到了生產(chǎn)者往topic里丟數(shù)據(jù)是存在partition上的,而partition持久化到磁盤是IO順序訪問的,并且是先寫緩存,隔一段時(shí)間或者數(shù)據(jù)量足夠大的時(shí)候才批量寫入磁盤的。
消費(fèi)者在讀的時(shí)候也很有講究:正常的讀磁盤數(shù)據(jù)是需要將內(nèi)核態(tài)數(shù)據(jù)拷貝到用戶態(tài)的,而Kafka 通過調(diào)用sendfile直接從內(nèi)核空間(DMA的)到內(nèi)核空間(Socket的),少做了一步拷貝的操作。
有的同學(xué)可能會(huì)產(chǎn)生疑問:消費(fèi)者是怎么知道自己消費(fèi)到哪里的呀?Kafka不是支持回溯嗎?那是怎么做的呀?
比如上面也提到:如果一個(gè)消費(fèi)者組中的某個(gè)消費(fèi)者掛了,那掛掉的消費(fèi)者所消費(fèi)的分區(qū)可能就由存活的消費(fèi)者消費(fèi)。那存活的消費(fèi)者是需要知道掛掉的消費(fèi)者消費(fèi)到哪了,不然怎么玩。
這里要引出offset了,Kafka就是用offset來表示消費(fèi)者的消費(fèi)進(jìn)度到哪了,每個(gè)消費(fèi)者會(huì)都有自己的offset。說白了offset就是表示消費(fèi)者的消費(fèi)進(jìn)度。
在以前版本的Kafka,這個(gè)offset是由Zookeeper來管理的,后來Kafka開發(fā)者認(rèn)為Zookeeper不合適大量的刪改操作,于是把offset在broker以內(nèi)部topic(__consumer_offsets)的方式來保存起來。
每次消費(fèi)者消費(fèi)的時(shí)候,都會(huì)提交這個(gè)offset,Kafka可以讓你選擇是自動(dòng)提交還是手動(dòng)提交。
既然提到了Zookeeper,那就多說一句。Zookeeper雖然在新版的Kafka中沒有用作于保存客戶端的offset,但是Zookeeper是Kafka一個(gè)重要的依賴。
探測broker和consumer的添加或移除。
負(fù)責(zé)維護(hù)所有partition的領(lǐng)導(dǎo)者/從屬者關(guān)系(主分區(qū)和備份分區(qū)),如果主分區(qū)掛了,需要選舉出備份分區(qū)作為主分區(qū)。
維護(hù)topic、partition等元配置信息
….
最后
通過這篇文章,文章開頭那幾個(gè)問題估計(jì)多多少少都懂一些啦。我來簡要回答一下:
使用消息隊(duì)列不可能是單機(jī)的(必然是分布式or集群)
Kafka天然是分布式的,往一個(gè)topic丟數(shù)據(jù),實(shí)際上就是往多個(gè)broker的partition存儲(chǔ)數(shù)據(jù)
數(shù)據(jù)寫到消息隊(duì)列,可能會(huì)存在數(shù)據(jù)丟失問題,數(shù)據(jù)在消息隊(duì)列需要持久化(磁盤?數(shù)據(jù)庫?Redis?分布式文件系統(tǒng)?)
Kafka會(huì)將partition以消息日志的方式(落磁盤)存儲(chǔ)起來,通過 順序訪問IO和緩存(等到一定的量或時(shí)間)才真正把數(shù)據(jù)寫到磁盤上,來提高速度。
想要保證消息(數(shù)據(jù))是有序的,怎么做?
Kafka會(huì)將數(shù)據(jù)寫到partition,單個(gè)partition的寫入是有順序的。如果要保證全局有序,那只能寫入一個(gè)partition中。如果要消費(fèi)也有序,消費(fèi)者也只能有一個(gè)。
為什么在消息隊(duì)列中重復(fù)消費(fèi)了數(shù)據(jù)
凡是分布式就無法避免網(wǎng)絡(luò)抖動(dòng)/機(jī)器宕機(jī)等問題的發(fā)生,很有可能消費(fèi)者A讀取了數(shù)據(jù),還沒來得及消費(fèi),就掛掉了。Zookeeper發(fā)現(xiàn)消費(fèi)者A掛了,讓消費(fèi)者B去消費(fèi)原本消費(fèi)者A的分區(qū),等消費(fèi)者A重連的時(shí)候,發(fā)現(xiàn)已經(jīng)重復(fù)消費(fèi)同一條數(shù)據(jù)了。(各種各樣的情況,消費(fèi)者超時(shí)等等都有可能…)
如果業(yè)務(wù)上不允許重復(fù)消費(fèi)的問題,最好消費(fèi)者那端做業(yè)務(wù)上的校驗(yàn)(如果已經(jīng)消費(fèi)過了,就不消費(fèi)了)
這篇文章主要是Kafka入門,Kafka還涉及到別的概念,以及還有別的東西。在我感覺中,很多的面試題都跟配置有關(guān),所以在解決某些問題的時(shí)候,先看看能不能通過現(xiàn)有配置解決掉(學(xué)多了框架,你就會(huì)發(fā)現(xiàn)很多官方的就已經(jīng)支持解決了,你做的可能改改配置/參數(shù)就完事了)
【END】
總結(jié)
以上是生活随笔為你收集整理的kafka topic 一段时间不消费_全网最通俗易懂的 Kafka 入门的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: alter table add colu
- 下一篇: 时分秒 java_JAVA 时分秒累加