《Kafka筆記》1、Kafka初識
阿新 • • 發佈:2020-10-18
[TOC]
# 一、初識Kafka
## 1 apache kafka簡介
Kafka是由Apache軟體基金會開發的一個開源流處理平臺,由Scala和Java編寫。Kafka是一種高吞吐量的分散式釋出訂閱訊息系統,它可以收集並處理使用者在網站中的所有動作流資料以及物聯網裝置的取樣資訊。
Apache Kafka是Apache軟體基金會的開源的流處理平臺,該平臺提供了訊息的訂閱與釋出的訊息佇列,一般用作**系統間解耦**、**非同步通訊**、**削峰填谷**等作用。同時Kafka又提供了Kafka streaming外掛包實現了實時線上流處理。相比較一些專業的流處理框架不同,Kafka-Streaming計算是執行在應用端,具有簡單、入門要求低、部署方便等優點。
- 訊息佇列Message Queue
- Kafka Streaming 流處理
## 2 訊息中介軟體kafka的使用場景
### 2.1 訂閱與釋出佇列
1、系統間解耦
2、非同步通訊
3、削峰填谷
![訊息中介軟體kafka的作用](https://note.youdao.com/yws/api/personal/file/7091EBC71D9D4C3591B4006D7C4211A7?method=download&shareKey=74c6255e7de2814440c6bea35293d697)
### 2.2 流處理
1、Kafka streaming相比較於其他流處理框架,例如stom和spark,flink,kafka是應用在應用端的流處理。而stom,spark和flink都是執行在服務端的流處理框架。
2、所以kafak流,比stom,spark,flink的部署方便,執行的環境要求的比較低,同時無需開闢新的的伺服器用來做流計算
3、所以kafka的流,被廣泛應用在分散式,微服務領域
## 3 kafka對資料的管理形式
**Message Queue : 訊息佇列**
訊息佇列是一種在分散式和大資料開發中不可或缺的**中介軟體**。在分散式開發或者大資料開發中通常使用訊息佇列進行緩衝、系統間解耦和削峰填谷等業務場景,常見的訊息佇列工作模式大致會分為兩大類:
- 至多一次:訊息生產者將資料寫入訊息系統,然後由消費者負責去拉去訊息伺服器中的訊息,一旦**訊息被確認消費之後** ,由**訊息伺服器主動刪除佇列中的資料**,這種消費方式一般只允許被一個消費者消費,並且**訊息佇列中的資料不允許被重複消費**,例如activeMQ。
- **沒有限制**:同上訴消費形式不同,生產者釋出完資料以後,**該訊息可以被多個消費者同時消費,並且同一個消費者可以多次消費訊息伺服器中的同一個記錄**。主要是因為訊息伺服器一般可以長時間儲存海量訊息。每個消費者都有自己的偏移量。例如Kafka
![至多一次和重複消費對比](https://note.youdao.com/yws/api/personal/file/91DED05FBFF3477DA48F5DA74650557B?method=download&shareKey=252366870f087d8bf703de30316c95e6)
## 4 kafka基礎架構
1、Kafka叢集(kafka往往通過多節點構成)以Topic形式負責分類叢集中的Record(訊息)每一個Record屬於一個Topic。每個Topic底層都會對應一組分割槽的日誌用於持久化Topic中的Record。
2、同時在Kafka叢集中,Topic的每一個日誌的分割槽都一定會有1個Borker(機器節點)擔當該分割槽的Leader,其他的Broker擔當該分割槽的follower,Leader負責分割槽資料的讀寫操作,follower負責同步改分割槽的資料。
3、這樣如果分割槽的Leader宕機,該分割槽的其他follower會選取出新的leader繼續負責該分割槽資料的讀寫。
4、每個分割槽也都有自己的副本(分割槽冗餘相互備份)。
5、其中叢集的中Leader的監控和Topic的部分元資料是儲存在Zookeeper中.
6、生產者傳送的訊息,只屬於一個topic。消費者可以訂閱多個topic。一旦訂閱者訂閱的topic有資料產生,便可以fetch它
![Kafka架構](https://note.youdao.com/yws/api/personal/file/3A09536576E847B5B77430B6E11D2E0A?method=download&shareKey=3f202ee0e8cb72da4528fd2ef6fc30dd)
7、hash(key)%分割槽數:不僅能夠使訊息均勻的落入我們的分割槽中,而且還可以是相同的key落入到相同的分割槽
8、分割槽因子:表示我們的每個分割槽要在叢集中存多少份
9、kafka中,所有的broker節點,既是某個分割槽的leader也可能是另外分割槽的follower。
![Kafka架構詳解](https://note.youdao.com/yws/api/personal/file/F5ED12D9F06941BC8E65C694D957962B?method=download&shareKey=66323369fd135a8dda27c7a8db25cf08)
10、如上圖,如果broker-0宕機,zookeeper會檢測到我們Topic01的partion0的leader宕機。會協調重新在broker-1和broker-2選擇partion0的leader。節點broker-0恢復服務後,我們zk叢集會重新協調分配
![Kafka叢集節點宕機](https://note.youdao.com/yws/api/personal/file/FF4AFFE5D58D44FE8F7AD89280477BF1?method=download&shareKey=cf7fc6c3805b6d7b55c6065d80eca1e5)
## 5 Kafka的主題(topics)和日誌(logs)
### 5.1 訊息釋出端
1、Kafka中所有訊息(record)是通過Topic為單位進行管理,每個Kafka中的Topic**通常會有多個訂閱者(也叫消費者)**,負責訂閱傳送到改Topic中的資料。Kafka負責管理叢集中每個Topic的一組日誌分割槽資料。
2、生產者將資料釋出到相應的Topic。負責選擇將哪個記錄(訊息)分發送到Topic中的哪個Partition。例如可以round-robin(輪詢)方式完成此操作,然而這種僅是為了**平衡負載**。也可以根據某些語義分割槽功能(例如基於記錄中的Key)進行此操作。
3、每組日誌分割槽是一個有序的不可變的的日誌序列(先進先出fifo),分割槽中的每一個Record都被分配了唯一的序列編號稱為是offset(當前訊息在序列中的位置),Kafka 叢集會持久化所有釋出到Topic中的Record資訊,該Record的持久化的時間是通過配置檔案指定,預設是168小時(7天)。`log.retention.hours=168`
5、Kafka底層會定期的檢查日誌檔案,然後將過期的資料從log中移除,由於**Kafka底層使用硬碟儲存**日誌檔案,因此使用Kafka長時間快取一些日誌檔案是不存在問題的。
6、由於遵循分割槽策略,每個partion的資料並不是相同的,也並非全域性有序的,既並非保證topic全域性先進先出。每個分割槽內部是有序的,總體構成的我們生產者生產在這個topic的全集的資料。**如果一定要保證在一個topic中全域性有序,我們可以指定topic中的分割槽數為1個即可**
![kafka分割槽訊息寫入](https://note.youdao.com/yws/api/personal/file/2FEC49292D8345928082C3CCA8681429?method=download&shareKey=8619a11e27f62b2262548b6993bc5830)
7、每個分割槽,都有叢集節點一個節點擔任leader。那麼如果要保證寫入速度快,我們只需要增加topic中的分割槽數目即可。**既增加分割槽可以提升kafka的寫入效能**
### 5.2 訊息消費端
1、在消費者消費Topic中資料的時候,**每個消費者會維護本次消費對應分割槽的偏移量**,消費者會在消費完一個批次的資料之後,會將本次消費的偏移量提交給Kafka叢集,因此對於每個消費者而言可以隨意的控制改消費者的偏移量。因此在Kafka中,消費者可以從一個topic分割槽中的任意位置讀取佇列資料,由於**每個消費者控制了自己的消費的偏移量**,因此多個消費者之間彼此相互獨立。**消費者每次提交給kafka叢集的偏移量,是該消費者下次需要讀取的起始位置**
![kafka消費資料](https://note.youdao.com/yws/api/personal/file/7E654B53F2B44743A6BE2CC9A540E989?method=download&shareKey=bb843a731d211de75770277cc87b7a9c)
2、Kafka中對Topic實現日誌分割槽的有以下目的:
- 首先,它們**允許日誌擴充套件到超出單個伺服器所能容納的大小**。每個單獨的分割槽都必須適合託管它的伺服器,但是一個Topic可能有很多分割槽,因此它可以處理任意數量的資料。
- 其次每個伺服器充當其某些分割槽的Leader,也可能充當其他分割槽的Follwer,因此群集中的負載得到了很好的平衡。
## 6 生產者&消費者&消費者組
1、**消費者使用Consumer Group名稱標記自己,並且釋出到Topic的每條記錄都會傳遞到每個訂閱Consumer Group中的一個消費者例項**。如果所有Consumer例項都具有相同的Consumer Group,那麼Topic中的記錄會在該ConsumerGroup中的Consumer例項進行均分消費;**如果所有Consumer例項具有不同的ConsumerGroup,則每條記錄將廣播到所有Consumer Group程序**。
> 解釋:對於kafka而言,只保證傳送到topic中的每條訊息,一定會發送到ConsumerGroup,但是到底傳送給了ConsumerGroup的哪個Consumer消費者例項,取決於消費者例項的一些配置
2、更常見的是,我們發現Topic具有少量的Consumer Group,**每個Consumer Group可以理解為一個“邏輯的訂閱者”。每個Consumer Group均由許多Consumer例項組成,以實現可伸縮性和容錯能力**。這無非就是釋出-訂閱模型,**其中訂閱者是消費者的叢集(消費者組)而不是單個程序**。這種消費方式Kafka會將Topic按照分割槽的方式均分給一個Consumer Group下的例項,**如果ConsumerGroup下有新的成員介入,則新介入的Consumer例項會去接管ConsumerGroup內其他消費者負責的某些分割槽,同樣如果一下ConsumerGroup下的有其他Consumer例項宕機,則由改ConsumerGroup其他例項接管**。
> 解釋:同一個消費者組,只能均分分割槽消費,不能重複消費某一個分割槽,不管該組有多少個消費者。不同消費者組,互不影響。見下圖
3、由於Kafka的Topic的分割槽策略,因此Kafka僅提供分割槽中記錄的有序性,也就意味著**相同Topic的不同分割槽記錄之間無順序**。因為針對於絕大多數的大資料應用和使用場景, 使用分割槽內部有序或者使用key進行分割槽策略已經足夠滿足絕大多數應用場景。但是,如果您需要記錄全域性有序,則**可以通過只有一個分割槽Topic來實現**,儘管這將**意味著每個ConsumerGroup只有一個Consumer程序,意味著我們會損傷kafka的高吞吐量**。
![消費者組消費](https://note.youdao.com/yws/api/personal/file/AEF72B934E15497CA443A3D3C10D8BE8?method=download&shareKey=388b66c033e5f8030e22f2d66fa4e9d7)
> 解釋:一般消費者組裡面消費者的數目,不會大於分割槽數目。如果大於,那麼會存在某個消費者不消費,浪費了資源。例如上圖在消費者組B增加一個消費者c5,那麼由於c1,c2,c3,c4已經安排好了,c5只能處於空閒狀態。但是如果c1,c2,c3,c4的某臺宕機,會有c5來接管
![消費者組冗餘情況](https://note.youdao.com/yws/api/personal/file/1EF13B3577DF475DBCAC3A66476D127C?method=download&shareKey=76a903238fd7e83505c750d31029df85)
> 原則意義上講,topic中的分割槽越多,我們定義消費者組中的消費者只需要保持一致,並行消費能力增強,就可以加快消費。本質還是加大topic中的分割槽數目。
> 所以增加kafka的topic中的分割槽數目,不僅僅可以增加我們的儲存,寫入能力。也可以間接增加我們並行消費topic的速度和能力
## 7 順序寫入和Zero-copy(高效能之道)
### 7.1 寫入效能提升之道(順序寫和mmap)
1、Kafka的**特性之一就是高吞吐率**,但是Kafka的訊息是儲存或快取在磁碟上的,一般認為在磁碟上讀寫資料是會降低效能的,但是**Kafka即使是普通的伺服器,Kafka也可以輕鬆支援每秒百萬級的寫入請求,超過了大部分的訊息中介軟體,這種特性也使得Kafka在日誌處理等海量資料場景廣泛應用**。Kafka會把收到的訊息都寫入到硬碟中,防止丟失資料。為了優化寫入速度Kafka採用了兩個技術**順序寫入**和**MMFile(記憶體對映檔案)** 。
2、因為硬碟是機械結構,每次讀寫都會定址->寫入,其中定址是一個“機械動作”,它是最耗時的(移動磁頭)。所以**硬碟最討厭隨機I/O,最喜歡順序I/O**。為了提高讀寫硬碟的速度,Kafka就是使用順序I/O。**這樣省去了大量的記憶體開銷以及節省了IO定址的時間**。但是單純的使用順序寫入,Kafka的寫入效能也不可能和記憶體進行對比,**因此Kafka的資料並不是實時的寫入硬碟中**。
3、Kafka充分利用了現代作業系統分頁儲存(page catch)來利用記憶體提高I/O效率。Memory Mapped Files(後面簡稱mmap)也稱為記憶體對映檔案,在64位作業系統中一般可以表示20G的資料檔案,它的**工作原理是直接利用作業系統的Page實現檔案到實體記憶體的直接對映。完成MMP對映後,使用者對記憶體的所有操作會被作業系統自動的重新整理到磁碟上,極大地降低了IO使用率**。
> 注:kafka直接把資料寫入到核心級別的記憶體中,算是寫入成功了,kafka不會主動重新整理核心級別的記憶體上的資料到磁碟上。而是由作業系統來重新整理,極大降低io的使用率。對於使用者而言,我們感知的kafak的寫入效率,直接逼近與記憶體寫入
![Kafka順序寫和mmap](https://note.youdao.com/yws/api/personal/file/36EBB09D94974E5FA82F5F1B0CBC4BFF?method=download&shareKey=57a3e8626117b4f095cb3c5607d78e32)
### 7.2 消費效能提升之道(zero-copy)
1、Kafka伺服器在響應客戶端讀取的時候,底層使用ZeroCopy技術,直接將磁碟無需拷貝到使用者空間,而是**直接將資料通過核心空間傳遞輸出,資料並沒有抵達使用者空間**。
2、傳統IO操作
- 1、使用者程序呼叫read等系統呼叫向作業系統發出IO請求,請求讀取資料到自己的記憶體緩衝區中。自己進入阻塞狀態。
- 2、作業系統收到請求後,進一步將IO請求傳送磁碟。
- 3、磁碟驅動器收到核心的IO請求,把資料從磁碟讀取到驅動器的緩衝中。此時不佔用CPU。當驅動器的緩衝區被讀滿後,向核心發起中斷訊號告知自己緩衝區已滿。
- 4、核心收到中斷,使用CPU時間將磁碟驅動器的快取中的資料拷貝到核心緩衝區中。
- 5、如果核心緩衝區的資料少於使用者申請的讀的資料,重複步驟3跟步驟4,直到核心緩衝區的資料足夠多為止。
- 6、將資料從核心緩衝區拷貝到使用者緩衝區,同時從系統呼叫中返回。完成任務
3、DMA讀取
- 1、使用者程序呼叫read等系統呼叫向作業系統發出IO請求,請求讀取資料到自己的記憶體緩衝區中。自己進入阻塞狀態。
- 2、作業系統收到請求後,進一步將IO請求傳送DMA。然後讓CPU幹別的活去。
- 3、DMA進一步將IO請求傳送給磁碟。
- 4.磁碟驅動器收到DMA的IO請求,把資料從磁碟讀取到驅動器的緩衝中。當驅動器的緩衝區被讀滿後,向DMA發起中斷訊號告知自己緩衝區已滿。
- 4、DMA收到磁碟驅動器的訊號,將磁碟驅動器的快取中的資料拷貝到核心緩衝區中。此時不佔用CPU。這個時候只要核心緩衝區的資料少於使用者申請的讀的資料,核心就會一直重複步驟3跟步驟4,直到核心緩衝區的資料足夠多為止。
- 5、當DMA讀取了足夠多的資料,就會發送中斷訊號給CPU。
- 6、CPU收到DMA的訊號,知道資料已經準備好,於是將資料從核心拷貝到使用者空間,系統呼叫返回。
> 注:跟IO中斷模式相比,DMA模式下,DMA就是CPU的一個代理,它負責了一部分的拷貝工作,從而減輕了CPU的負擔。DMA的優點就是:中斷少,CPU負擔低。
4、網路IO
- 一般方案:
1、檔案在磁碟中資料被copy到核心緩衝區
2、從核心緩衝區copy到使用者緩衝區
3、使用者緩衝區copy到核心與socket相關的緩衝區。
4、資料從socket緩衝區copy到相關協議引擎傳送出去
- Zero拷貝
1、檔案在磁碟中資料被copy到核心緩衝區
2、從核心緩衝區copy到核心與socket相關的緩衝區。
3、資料從socket緩衝區copy到相關協議引擎傳送出去
![常規io](https://note.youdao.com/yws/api/personal/file/619F687BD77E43538E4E6A7AC8E34EF7?method=download&shareKey=0642b3f7caa311c2e2c585e1dd56ed4f)
![zeroCopy](https://note.youdao.com/yws/api/personal/file/E94800E86BF049048794F7520BB42AA2?method=download&shareKey=43bed24c2f10465bf717d441993219e3)
## 本章小結
1.佇列的使用場景
- 解耦、非同步通訊、削峰填谷
2.Kafka架構和基本概念
- topic、分割槽/分割槽副本因子、offset、順序寫、zeroCopy
- 生產者、消費者|消