一、我與快遞小哥的故事
一個很正常的一個作業日,老周正在忙著啪啪啪的敲代碼,辦公司好像安靜的只剩敲代碼的聲音,突然,我的電話鈴聲響起了,頓時打破了這種安靜,
我:喂,哪位?
快遞小哥:我是順豐快遞的,你有個包裹,請問你現在在家嗎?
我:哦,我現在不在家,晚上你再幫我送過來吧,
快遞小哥:要不我幫你放在菜鳥驛站吧?
我:可以可以,謝謝了,
還好有菜鳥驛站,不然作業日加班到很晚才回家,晚上快遞小哥又下班了,得等到周末我在家快遞小哥才能幫我送了,如果沒有菜鳥驛站的話,我們來看下快遞小哥與我的互動圖:

要是有菜鳥驛站的話,我們再來看下互動圖:

上面故事中的菜鳥驛站就是訊息佇列,也就是我們本篇要講的 Kafka;而快遞小哥就是生產者,老周就是消費者,老周一直很忙沒去菜鳥驛站取快遞,就是訊息積壓,我給快遞小哥發訊息說,確認快遞已經取到了,就是 ACK 機制,
小伙伴們可能發現了菜鳥驛站的好處了,真香,
這里老周來總結幾點訊息佇列的好處也就是使用場景:
應用解耦
到了什么 618、雙 11,快遞小哥要忙瘋了,他得每個電話打,然后詢問客戶在不在家,幾點有時間,這樣完全依賴識訓人,那快遞小哥估計要瘋,有了菜鳥驛站,快遞小哥直接把快遞放在菜鳥驛站,然后通知識訓人過去取就好了,這就讓識訓人與快遞小哥實作了解耦,在軟體行業的話,即應用解耦,異步處理
要是沒有菜鳥驛站,快遞小哥得在樓下等你下來拿快遞,拿完了他才能走,這叫同步處理,有了菜鳥驛站,快遞小哥把你的快遞放在了菜鳥驛站,通知你去取,然后他繼續干別的事情去了,這叫異步處理,異步處理明顯提升了快遞小哥的作業效率,在軟體中,寫異步代碼同樣能提升代碼的執行效率,流量削鋒
雙十一老周買了很多東西,不同的店發的快遞不一樣,有順豐、韻達、中通、申通,都在我周日上午十點這個時間段下去拿,搞得我下樓好頻繁這個時間段,有了菜鳥驛站,我可以吃中午飯再下去順便拿下快遞,這就達到了十點那個時間段的流量削鋒效果,
我與快遞小哥的故事是真實發生的哈,正好我有個讀者前段時間面試順豐的時候被問到 Kafka 了,要我出 Kafka 的內容,所以有了靈感寫了這篇文章,


二、Kafka 介紹
Kafka 是最初由 Linkedin 公司開發,是一個 分布式、磁區的、多副本的、多生產者、多訂閱者,基于zookeeper 協調的分布式訊息系統,常見可以用于 web/nginx 日志、訪問日志,訊息服務等,
Linkedin 于 2010 年貢獻給了 Apache 基金會并成為頂級開源專案,
2.1 基于zookeeper 協調
這里老周要提一下,Kafka 2.8.0 版本實作了 Raft 分布式一致性機制,意味著可以脫離 ZooKeeper 獨立運行了,
ZooKeeper 在 Kafka 中扮演著重要的角色,用來存盤 Kafka 的元資料,ZooKeeper 存盤著 Partition 和 Broker 的元資料 ,同時也負責 Kafka Controller 的選舉作業,
對于 Kafka 來講,ZooKeeper 是一套外部系統,要想部署一套 Kafka 集群,就要同時部署、管理、監控 ZooKeeper,ZooKeeper 有自己的配置方式、管理工具,和 Kafka 完全不一樣,所以,一起搞兩套分布式系統,自然就提升了復雜度,也更容易出現問題,有時作業量還會加倍,例如要開啟一些安全特性,Kafka 和 ZooKeeper 中都需要配置,除了復雜度,外部存盤也會降低系統效率,
例如:
- Kafka 集群每次啟動的時候,Controller 必須從 ZooKeeper 加載集群的狀態資訊,
- 選舉出一個新的 Controller 之后也會比較麻煩,因為需要加載元資料,而此時元資料的量可能已經非常大了,這就產生了效率問題,
所以,ZooKeeper 帶來的復雜度、系統效率這兩個問題已經成為 Kafka 的痛點,Kafka 團隊一直在努力去除對 ZooKeeper 的依賴,Kafka 2.8.0 這個版本終于實作了,
使用 Raft 模式之后,元資料、配置資訊都會保存在 @metadata 這個 Topic 中,自動在集群中復制,這樣 Kafka 就會簡單輕巧很多,
但需要注意的是,Zookeeper-less Kafka 還屬于早期版本,并不完善,所以,現在不要應用在線上產品環境中,
2.2 主要應用場景
- 日志收集系統
- 訊息系統
2.3 Kafka 主要設計目標
- 以時間復雜度為
O(1)的方式提供訊息持久化能力,即使對TB級以上資料也能保證常數時間的訪問性能, - 高吞吐率,即使在非常廉價的商用機器上也能做到單機支持每秒
100K條訊息的傳輸, - 支持
Kafka Server間的訊息磁區,及分布式消費,同時保證每個partition傳輸, - 同時支持離線資料處理和實時資料處理
- 支持在線水平擴展
2.4 兩種主要的訊息傳遞模式
2.4.1 點對點模式

點對點模式通常是基于拉取或者輪詢的訊息傳送模型,這個模型的特點是發送到佇列的訊息被一個且只有一個消費者進行處理,生產者將訊息放入訊息佇列后,由消費者主動的去拉取訊息進行消費,點對點模型的的優點是消費者拉取訊息的頻率可以由自己控制,但是訊息佇列是否有訊息需要消費,在消費者端無法感知,所以在消費者端需要額外的執行緒去監控,
2.4.2 發布訂閱模式

發布訂閱模式是一個基于訊息送的訊息傳送模型,該模型可以有多種不同的訂閱者,生產者將訊息放入訊息佇列后,佇列會將訊息推送給訂閱過該類訊息的消費者,由于是消費者被動接收推送,所以無需感知訊息佇列是否有待消費的訊息!但是 consumer1、consumer2、consumer3 由于機器性能不一樣,所以處理訊息的能力也會不一樣,但訊息佇列卻無法感知消費者消費的速度!所以推送的速度成了發布訂閱模模式的一個問題!假設三個消費者處理速度分別是 8M/s、5M/s、2M/s,如果佇列推送的速度為5M/s,則 consumer3 無法承受!如果佇列推送的速度為 2M/s,則 consumer1、consumer2 會出現資源的極大浪費!
大部分的訊息系統選用發布訂閱模式, Kafka 就是一種發布訂閱模式,
2.5 Kafka 四個核心 API
Producer API:允許應用程式將記錄流發布到一個或多個 Kafka 主題,Consumer API:允許應用程式訂閱一個或多個主題并處理為其生成的記錄流,Streams API:允許應用程式充當流處理器,使用一個或多個主題的輸入流,并生成一個或多個輸出主題的輸出流,從而有效地將輸入流轉換為輸出流,Connector API:允許構建和運行將 Kafka 主題連接到現有應用程式或資料系統的可重用生產者或使用者,例如,關系資料庫的連接器可能會捕獲對表的所有更改,
三、Kafka 的優勢
高吞吐量:單機每秒處理幾十上百萬的訊息量,即使存盤了許多的訊息,它也保持穩定的性能,高性能:單節點支持上千個客戶端,并保證零停機和零資料丟失,持久化資料存盤:將訊息持久化到磁盤,通過將資料持久化到硬碟以及防止資料丟失,(零拷貝、 順序讀,順序寫、利用的頁快取)分布式系統,易于向外擴展,所有的 Producer、Broker 和 Consumer 都會有多個,均為分布式的,
無需停機即可擴展機器,多個 Producer、Consumer 可能是不同的應用,可靠性:Kafka 是分布式、磁區、復制和容錯的,客戶端狀態維護:訊息被處理的狀態是在 Consumer 端維護,而不是由 server 端維護,當失敗時能自動平衡,支持 online 和 offline 的場景支持多種客戶端語言,Kafka 支持 Java、.NET、PHP、Python 等多種語言,
四、Kafka 的應用場景
4.1 日志收集
Kafka 可以收集各種服務的 Log,通過 Kafka 以統一介面服務的方式開放給各種 Consumer,
4.2 訊息系統
解耦生產者和消費者、快取訊息等,
4.3 用戶活動跟蹤
- Kafka 經常被用來記錄 Web 用戶或者 App 用戶的各種活動,如瀏覽網頁、搜索、點擊等活動,
- 這些活動資訊被各個服務器發布到 Kafka 的 Topic 中,然后消費者通過訂閱這些 Topic 來做實時的監控分析,亦可保存到資料庫,
4.4 運營指標
Kafka 也經常用來記錄運營監控資料,包括收集各種分布式應用的資料,生產各種操作的集中反饋,比如報警和報告,
4.5 流式處理
比如 Spark Streaming 和 Storm,
五、基礎架構
5.1 Kafka 架構圖

5.2 訊息和批次
- Kafka 的資料單元稱為訊息,可以把訊息看成是資料庫里的一個“資料行”或一條“記錄”,訊息由位元組陣列組成,
- 訊息有鍵,鍵也是一個位元組陣列,當訊息以一種可控的方式寫入不同的磁區時,會用到鍵,
- 為了提高效率,訊息被分批寫入 Kafka,批次就是一組訊息,這些訊息屬于同一個主題和磁區,
- 把訊息分成批次可以減少網路開銷,批次越大,單位時間內處理的訊息就越多,單個訊息的傳輸時間就越長,批次資料會被壓縮,這樣可以提升資料的傳輸和存盤能力,但是需要更多的計算處理,
5.3 模式
- 訊息模式(schema)有許多可用的選項,以便于理解,如 JSON 和 XML,但是它們缺乏強型別處理能力,Kafka 的許多開發者喜歡使用 Apache Avro,Avro 提供了一種緊湊的序列化格式,模式和訊息體分開,當模式發生變化時,不需要重新生成代碼,它還支持強型別和模式進化,其版本既向前兼容,也向后兼容,
- 資料格式的一致性對 Kafka 很重要,因為它消除了訊息讀寫操作之間的耦合性,
5.4 主題和磁區
- Kafka 的訊息通過主題進行分類,主題可比是
資料庫的表或者檔案系統里的檔案夾, - 主題可以被分為若干磁區,一個主題通過磁區分布于 Kafka 集群中,提供了橫向擴展的能力,

5.5 生產者和消費者
-
生產者創建訊息,消費者消費訊息,
-
一個訊息被發布到一個特定的主題上,
-
生產者在默認情況下把訊息均衡地分布到主題的所有磁區上:
- 直接指定訊息的磁區
- 根據訊息的 key 散列取模得出磁區
- 輪詢指定磁區
-
消費者通過偏移量來區分已經讀過的訊息,從而消費訊息,
-
消費者是消費組的一部分,消費組保證每個磁區只能被一個消費者使用,避免重復消費,

5.6 broker 和集群
- 一個獨立的 Kafka 服務器稱為 broker,
- broker 接收來自生產者的訊息,為訊息設定偏移量,并提交訊息到磁盤保存,
- broker 為消費者提供服務,對讀取磁區的請求做出回應,回傳已經提交到磁盤上的訊息,
- 單個 broker 可以輕松處理數千個磁區以及每秒百萬級的訊息量,

每個集群都有一個 broker 是集群控制器(自動從集群的活躍成員中選舉出來),
控制器負責管理作業:
- 將磁區分配給 broker
- 監控 broker
集群中一個磁區屬于一個 broker,該 broker 稱為磁區首領,
一個磁區可以分配給多個 broker,此時會發生磁區復制,
磁區的復制提供了訊息冗余, 高可用 ,副本磁區不負責處理訊息的讀寫,
六、核心概念
6.1 Producer
生產者創建訊息,
該角色將訊息發布到 Kafka 的 topic 中,broker 接收到生產者發送的訊息后,broker 將該訊息追加到當前用于追加資料的 segment 檔案中,
一般情況下,一個訊息會被發布到一個特定的主題上,
- 默認情況下通過輪詢把訊息均衡地分布到主題的所有磁區上,
- 在某些情況下,生產者會把訊息直接寫到指定的磁區,這通常是通過訊息鍵和磁區器來實作的,磁區器為鍵生成一個散列值,并將其映射到指定的磁區上,這樣可以保證包含同一個鍵的訊息會被寫到同一個磁區上,
- 生產者也可以使用自定義的磁區器,根據不同的業務規則將訊息映射到磁區,
6.2 Consumer
消費者讀取訊息,
- 消費者訂閱一個或多個主題,并按照訊息生成的順序讀取它們,
- 消費者通過檢查訊息的偏移量來區分已經讀取過的訊息,偏移量是另一種元資料,它是一個不斷遞增的整數值,在創建訊息時,Kafka 會把它添加到訊息里,在給定的磁區里,每個訊息的偏移量都是唯一的,消費者把每個磁區最后讀取的訊息偏移量保存在 Zookeeper 或 Kafka上 ,如果消費者關倍訓重啟,它的讀取狀態不會丟失,
- 消費者是消費組的一部分,群組保證每個磁區只能被一個消費者使用,
- 如果一個消費者失效,消費組里的其他消費者可以接管失效消費者的作業,再平衡,磁區重新分配,

6.3 Broker
一個獨立的 Kafka 服務器被稱為 broker,
broker 為消費者提供服務,對讀取磁區的請求作出回應,回傳已經提交到磁盤上的訊息,
- 如果某 topic 有 N 個 partition,集群有 N 個 broker,那么每個 broker 存盤該 topic 的一個 partition,
- 如果某 topic 有 N 個 partition,集群有 (N+M) 個 broker,那么其中有 N 個 broker 存盤該 topic 的一個partition,剩下的 M 個 broker 不存盤該 topic 的 partition 資料,
- 如果某 topic 有 N 個 partition,集群中 broker 數目少于 N 個,那么一個 broker 存盤該 topic 的一個或多個 partition,在實際生產環境中,盡量避免這種情況的發生,這種情況容易導致 Kafka 集群資料不均衡,
broker 是集群的組成部分,每個集群都有一個 broker 同時充當了集群控制器的角色(自動從集群的活躍成員中選舉出來),
控制器負責管理作業,包括將磁區分配給 broker 和監控 broker,
在集群中,一個磁區從屬于一個 broker,該 broker 被稱為磁區的首領,

6.4 Topic
每條發布到 Kafka 集群的訊息都有一個類別,這個類別被稱為 Topic,
物理上不同 Topic 的訊息分開存盤,
主題就好比資料庫的表,尤其是分庫分表之后的邏輯表,
6.5 Partition
- 主題可以被分為若干個磁區,一個磁區就是一個提交日志,
- 訊息以追加的方式寫入磁區,然后以先入先出的順序讀取,
- 無法在整個主題范圍內保證訊息的順序,但可以保證訊息在單個磁區內的順序,
- Kafka 通過磁區來實作資料冗余和伸縮性,
- 在需要嚴格保證訊息的消費順序的場景下,需要將 partition 數目設為1,
6.6 Replicas
Kafka 使用主題來組織資料,每個主題被分為若干個磁區,每個磁區有多個副本,那些副本被保存在broker 上,每個broker 可以保存成百上千個屬于不同主題和磁區的副本,
副本有以下兩種型別:
-
首領副本
每個磁區都有一個首領副本,為了保證一致性,所有生產者請求和消費者請求都會經過這個副本, -
跟隨者副本
首領以外的副本都是跟隨者副本,跟隨者副本不處理來自客戶端的請求,它們唯一的任務就是從首領那里復制訊息,保持與首領一致的狀態,如果首領發生崩潰,其中的一個跟隨者會被提升為新首領,
6.7 Offset
6.7.1 生產者 Offset
訊息寫入的時候,每一個磁區都有一個 offset,這個 offset 就是生產者的 offset,同時也是這個磁區的最新最大的 offset,
有些時候沒有指定某一個磁區的 offset,這個作業 kafka 幫我們完成,

6.7.2 消費者 Offset

這是某一個磁區的 offset 情況,生產者寫入的 offset 是最新最大的值是12,而當 Consumer A 進行消費時,從 0 開始消費,一直消費到了 9,消費者的 offset 就記錄在 9,Consumer B 就紀錄在了 11,等下一次他們再來消費時,他們可以選擇接著上一次的位置消費,當然也可以選擇從頭消費,或者跳到最近的記錄并從“現在”開始消費,
6.8、副本
Kafka 通過副本保證高可用,副本分為首領副本(Leader)和跟隨者副本(Follower),
跟隨者副本包括同步副本和不同步副本,在發生首領副本切換的時候,只有同步副本可以切換為首領副本,
6.8.1 AR
磁區中的所有副本統稱為AR(Assigned Repllicas),
AR=ISR+OSR
6.8.2 ISR
所有與leader副本保持一定程度同步的副本(包括Leader)組成ISR(In-Sync Replicas),ISR 集合是 AR 集合中的一個子集,訊息會先發送到 leader 副本,然后 follower 副本才能從 leader 副本中拉取訊息進行同步,同步期間內 follower 副本相對于 leader 副本而言會有一定程度的滯后,前面所說的“一定程度”是指可以忍受的滯后范圍,這個范圍可以通過引數進行配置,
6.8.3 OSR
與leader副本同步滯后過多的副本(不包括leader)副本,組成OSR(Out-Sync Relipcas),在正常情況下,所有的 follower 副本都應該與 leader 副本保持一定程度的同步,即 AR=ISR,OSR 集合為空,
6.8.4 HW
HW 是High Watermak的縮寫, 俗稱高水位,它表示了一個特定訊息的偏移量(offset),消費者只能拉取到這個offset之前的訊息,
6.8.5 LEO
LEO 是Log End Offset的縮寫,它表示了當前日志檔案中下一條待寫入訊息的 offset,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/293005.html
標籤:其他
上一篇:1、基于STM32的音樂噴泉√♥
下一篇:手動實作51單片機函式切換
