當前位置:
首頁 > 最新 > 消息隊列 MQ 專欄

消息隊列 MQ 專欄

源碼精品專欄

Kafka 特點

Kafka 最早是由 LinkedIn 公司開發一種分散式的基於發布/訂閱的消息系統,之後成為 Apache 的頂級項目。主要特點如下:

1. 同時為發布和訂閱提供高吞吐量

Kafka 的設計目標是以時間複雜度為 O(1) 的方式提供消息持久化能力,即使對TB 級以上數據也能保證常數時間的訪問性能。即使在非常廉價的商用機器上也能做到單機支持每秒 100K 條消息的傳輸。

2. 消息持久化

將消息持久化到磁碟,因此可用於批量消費,例如 ETL 以及實時應用程序。通過將數據持久化到硬碟以及 replication 防止數據丟失。

3. 分散式

支持 Server 間的消息分區及分散式消費,同時保證每個 partition 內的消息順序傳輸。這樣易於向外擴展,所有的producer、broker 和 consumer 都會有多個,均為分散式的。無需停機即可擴展機器。

4. 消費消息採用 pull 模式

消息被處理的狀態是在 consumer 端維護,而不是由 server 端維護,broker 無狀態,consumer 自己保存 offset。

5. 支持 online 和 offline 的場景。

同時支持離線數據處理和實時數據處理。

Kafka 中的基本概念


img

1. Broker

Kafka 集群中的一台或多台伺服器統稱為 Broker

2. Topic

每條發布到 Kafka 的消息都有一個類別,這個類別被稱為 Topic 。(物理上不同Topic 的消息分開存儲。邏輯上一個 Topic 的消息雖然保存於一個或多個broker上,但用戶只需指定消息的 Topic 即可生產或消費數據而不必關心數據存於何處)

3. Partition

Topic 物理上的分組,一個 Topic 可以分為多個 Partition ,每個 Partition 是一個有序的隊列。Partition 中的每條消息都會被分配一個有序的 id(offset)

4. Producer

消息和數據的生產者,可以理解為往 Kafka 發消息的客戶端

5. Consumer

消息和數據的消費者,可以理解為從 Kafka 取消息的客戶端

6. Consumer Group

每個 Consumer 屬於一個特定的 Consumer Group(可為每個 Consumer 指定Group Name,若不指定 Group Name 則屬於默認的 Group)。這是 Kafka 用來實現一個 Topic 消息的廣播(發給所有的 Consumer )和單播(發給任意一個 Consumer )的手段。一個 Topic 可以有多個 Consumer Group。Topic 的消息會複製(不是真的複製,是概念上的)到所有的 Consumer Group,但每個 Consumer Group 只會把消息發給該 Consumer Group 中的一個 Consumer。如果要實現廣播,只要每個 Consumer 有一個獨立的 Consumer Group 就可以了。如果要實現單播只要所有的 Consumer 在同一個 Consumer Group 。用 Consumer Group 還可以將 Consumer 進行自由的分組而不需要多次發送消息到不同的 Topic 。

Kafka 安裝

Mac 用戶用 HomeBrew 來安裝,安裝前要先更新 brew

接著安裝 kafka

安裝完成之後可以查看 kafka 的配置文件

kafka 配置文件

kafka 需要用到 zookeeper,HomeBrew 安裝kafka 的時候會同時安裝 zookeeper。下面先啟動 zookeeper:

接著啟動 kafka

創建 topic,設置 partition 數量為2,topic 的名字叫 test-topic,下面的例子都用這個 topic

查看創建的 topic

Kafka 命令行測試

發送消息

消費消息

刪除 topic

查看所有 topic

物理刪除 topic

Java 客戶端訪問

1. maven工程的pom文件中添加依賴

2. 消息生產者

3. 消息消費者

4. 啟動 zookeeper

5. 啟動 kafka 伺服器

6. 運行 Consumer

先運行 Consumer ,這樣當生產者發送消息的時候能在消費者後端看到消息記錄。

7. 運行 Producer

運行 Producer,發布幾條消息,在 Consumer 的控制台能看到接收的消息

Consumer 控制台

Kafka 集群配置

kafka 的集群配置一般有三種,即: single node - single broker ,single node - multiple broker ,multiple node - multiple broker

前兩種實際上官網有介紹。

single node - single broker


2. 啟動 kafka broker

3. 創建一個 kafka topic

4. 啟動 producer 發送信息

broker-list 和 topic 這兩個參數是必須的,broker-list 指定要連接的 broker 的地址,格式為 node_address:port 。topic 是必須的,因為需要發送消息給訂閱了該topic 的 consumer group 。現在可以在命令行里輸入一些信息,每一行會被作為一個消息。

發送消息5. 啟動 consumer 消費消息

在不同的終端窗口裡分別啟動 zookeeper、broker、producer、consumer 後,在producer 終端里輸入消息,消息就會在 consumer 終端中顯示了。

消息顯示

single node - multiple broker

2. 啟動broker

如果需要在單個節點(即一台機子)上面啟動多個 broker(這裡作為例子啟動三個 broker),需要準備多個server.properties文件即可,所以需要複製 /usr/local/etc/kafka/server.properties 文件。因為需要為每個 broker 指定單獨的屬性配置文件,其中 broker.id 、 port 、 log.dir 這三個屬性必須是不同的。

新建一個 kafka-example 目錄和三個存放日誌的目錄

複製 /usr/local/etc/kafka/server.properties 文件三份

在 broker1 的配置文件 server-1.properties 中,相關要修改的參數為:

broker2 的配置文件 server-2.properties 中,相關要修改的參數為:

broker3 的配置文件 server-3.properties 中,相關要修改的參數為:

啟動每個 broker

3. 創建 topic

創建一個名為 topic-singlenode-multiplebroker 的topic

4. 啟動 producer 發送信息

如果一個 producer 需要連接多個 broker 則需要傳遞參數 broker-list

5. 啟動 consumer 消費消息

單節點多 broker 消費消息

multiple node - multiple broker


搭建 zookeeper 集群

1. Kafka 的集群配置

由於是多節點多 broker 的,所以每個 broker 的配置文件 server.properties 都要按以上說明修改

2. producer 的配置修改

3. consumer 的配置修改

Kafka 高可靠性配置

要保證數據寫入到 Kafka 是安全的、高可靠的,需要如下的配置:

1. topic 的配置

2. broker 的配置

3. producer 的配置

Kafka 高吞吐量的秘訣

消息中間件從功能上看就是寫入數據、讀取數據兩大類,優化也可以從這兩方面來看。

為了優化寫入速度 Kafak 採用以下技術:

1. 順序寫入

磁碟大多數都還是機械結構(SSD不在討論的範圍內),如果將消息以隨機寫的方式存入磁碟,就需要按柱面、磁頭、扇區的方式定址,緩慢的機械運動(相對內存)會消耗大量時間,導致磁碟的寫入速度與內存寫入速度差好幾個數量級。為了規避隨機寫帶來的時間消耗,Kafka 採取了順序寫的方式存儲數據,如下圖所示:

順序寫

消費消息

2. 內存映射文件

即便是順序寫入硬碟,硬碟的訪問速度還是不可能追上內存。所以 Kafka 的數據並不是實時的寫入硬碟,它充分利用了現代操作系統分頁存儲來利用內存提高I/O效率。Memory Mapped Files (後面簡稱mmap)也被翻譯成內存映射文件,在64位操作系統中一般可以表示 20G 的數據文件,它的工作原理是直接利用操作系統的 Page 來實現文件到物理內存的直接映射。完成映射之後對物理內存的操作會被同步到硬碟上(由操作系統在適當的時候)。通過 mmap 進程像讀寫硬碟一樣讀寫內存,也不必關心內存的大小,有虛擬內存為我們兜底。使用這種方式可以獲取很大的 I/O 提升,因為它省去了用戶空間到內核空間複製的開銷(調用文件的 read 函數會把數據先放到內核空間的內存中,然後再複製到用戶空間的內存中)但這樣也有一個很明顯的缺陷——不可靠,寫到 mmap 中的數據並沒有被真正的寫到硬碟,操作系統會在程序主動調用 flush 的時候才把數據真正的寫到硬碟。所以 Kafka 提供了一個參數—— producer.type 來控制是不是主動 flush,如果Kafka 寫入到 mmap 之後就立即 flush 然後再返回 Producer 叫同步(sync);如果寫入 mmap 之後立即返回,Producer 不調用 flush ,就叫非同步(async)。

3. 標準化二進位消息格式

為了避免無效率的位元組複製,尤其是在負載比較高的情況下影響是顯著的。為了避免這種情況,Kafka 採用由 Producer,Broker 和 Consumer 共享的標準化二進位消息格式,這樣數據塊就可以在它們之間自由傳輸,無需轉換,降低了位元組複製的成本開銷。

而在讀取速度的優化上 Kafak 採取的主要是零拷貝

零拷貝(Zero Copy)的技術:

傳統模式下我們從硬碟讀取一個文件是這樣的

文件傳輸到 Socket 的常規方式

(2) 應用將數據從內核空間讀到用戶空間的緩存中

(3) 應用將數據寫會內核空間的套接字緩存中

(4)操作系統將數據從套接字緩存寫到網卡緩存中,以便將數據經網路發出

這樣做明顯是低效的,這裡有四次拷貝,兩次系統調用。針對這種情況 Unix 操作系統提供了一個優化的路徑,用於將數據從頁緩存區傳輸到 socket。在 Linux 中,是通過 sendfile 系統調用來完成的。Java提供了訪問這個系統調用的方法:FileChannel.transferTo API。這種方式只需要一次拷貝:操作系統將數據直接從頁緩存發送到網路上,在這個優化的路徑中,只有最後一步將數據拷貝到網卡緩存中是需要的。

零拷貝方式傳輸到 Socket

Kafka 速度的秘訣在於它把所有的消息都變成一個的文件。通過 mmap 提高 I/O的速度,寫入數據的時候是末尾添加所以速度最優;讀取數據的時候配合sendfile 直接暴力輸出。所以單純的去測試 MQ 的速度沒有任何意義,Kafka 的這種暴力的做法已經脫了 MQ 的底褲,更像是一個暴力的數據傳送器。

知識星球

目前在知識星球(https://t.zsxq.com/2VbiaEu)更新了如下 Dubbo 源碼解析如下:

01. 調試環境搭建

02. 項目結構一覽

03. API 配置(一)之應用

04. API 配置(二)之服務提供者

05. API 配置(三)之服務消費者

06. 屬性配置

07. XML 配置

08. 核心流程一覽

09. 拓展機制 SPI

10. 線程池

...

一共 60 篇++


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 芋道源碼 的精彩文章:

網關 Spring-Cloud-Gateway 源碼解析——路由之RouteDefinitionLocator一覽

TAG:芋道源碼 |