kafka對於構建實時的資料管道和流應用是很有用的。
Apache Kafka是一個分散式的流平臺。這是什麼意思呢?
我們考慮流平臺有三個關鍵的能力:
- 它可以釋出訂閱流。這一點和訊息佇列或者企業訊息系統很類似。
- 它可以儲存流,並且可以容錯。
- 它可以處理流
Kafa有什麼用呢?
它被用於兩類應用:
- 在系統和應用之間構建實時的流管道
- 構建實時的流應用
那麼Kafka是怎樣做到這些事情的呢?
首先來看一些概念:
- Kafka是以叢集方式執行的
- Kafka叢集將流記錄儲存在被叫做topics的分類中
- 每一條記錄由一個key,一個value和一個timestamp組成
Kafka有四個核心的API:
- Producer API允許一個應用釋出一條流記錄到一個或者多個topics中
- Consumer API允許一個應用訂閱一個或多個topics,並且處理記錄流
- Streams API允許一個應用充當流處理器的角色,從一個或多個topics那裡消費一個輸入流並且生產一個輸出流到一個或多個topics,有效的將輸入流轉換為輸出流
- Connector API允許構建並執行可重用的可以將Kafka連線到已存在的應用或者資料系統上的producer或者consumer。例如,連線關係型資料庫。
在Kafka中,客戶端和伺服器端的通訊被做成是簡單的、高效能的、基於TCP協議的。
Topics and Logs
讓我們首先深入到核心抽象,Kafka提供a stream of records —— the topic
一個topic是一個分類,記錄是被髮布到這裡面的。在Kafka中,topics總是有多個訂閱者的;因此,一個topic可以有多個0個,1個,或者多個消費者來訂閱的。
每個topic,Kafka叢集維護一個partitioned log(分割槽日誌),它們看起來是這個樣子的:
每個分割槽都是一個有序的、不可變的序列,這些序列都是結構化的提交日誌。分割槽中的每個記錄都被指定了一個序列id編號,被稱之為offset,而且它是分割槽中每條記錄的唯一標識。
Kafka叢集操持所有的釋出記錄,無論這些記錄是否已經被消費,這一點是可以配置的。例如,如果這個保留策略設定的是2天,那麼一個記錄被髮布過了2天以後它仍然可以被消費,但是為了騰出空間來,它可能會被丟棄。Kaka的效能是高效的穩定的,所有儲存資料很長時間不是一個問題。
事實上,後設資料是儲存在每個消費者那裡的,最基本的是offset或者叫position,它們都是以消費者日誌形式儲存的。offset是由消費者來控制的:通常一個消費者會增長它的偏移量,事實上,自從消費者可以控制位置它可以以任意順序消費記錄。例如,一個消費者可以重置到一箇舊的offset以處理之前的記錄。
這個特性就意味著,kafka的消費者是非常廉價的 —— 它們可以來去自如而不受叢集和其它消費者的影響。
日誌分割槽有幾個目的。第一,允許日誌是伸縮的,大小可以超過單個伺服器,每一個獨立的分割槽必須安裝在它所在主機的那個伺服器上,但是一個topic可以有多個分割槽,所有它可以處理任意數量的資料。第二,作為一個並行單元。
Distribution
日誌分割槽是被分佈在叢集中的伺服器上的,每個伺服器處理資料和請求都共享這些分割槽。為了容錯,每個分割槽會交叉複製,副本的資料是可以配置的。
每個分割槽中有一個伺服器充當“leader”,有0個或者多個伺服器充當“followers”。leader處理所有的讀和寫請求,而follower被動的從leader那裡複製。如果leader失敗了,其中一個follower將自動成為新的leader。每個充當leader的伺服器可能是一些分割槽的leader,同時又是另一些分割槽的follower,所以在叢集中負載是平衡的。
Producers
生成者釋出資料到topics。生產者負責選擇哪個記錄指定到哪個分割槽。可以以一個輪詢的方式簡單的來實現負載均衡。
Consumers
消費者用一個“consumer group name”來標記它們自己,topic中的每個記錄被投遞到一個訂閱者消費組中的一個消費者例項。每個消費者例項分開處理。
如果所有的消費者例項都在相同的消費者組中,那麼記錄有效的在消費者之間負載均衡。
如果所有的消費者例項在不同的消費者組中,那麼每一條記錄都會被廣播給所有的消費者。
如圖,一個Kafka叢集有2個伺服器,4個分割槽(P0—P3),2個消費者分組。消費者分組A有2個消費者例項,組B有4個。
通常,我們會發現,topic有許多消費者分組,每個組都是一個"logical subscriber"(邏輯訂閱者)。每個組由許多消費者例項組成,例項是可伸縮的可容錯的。
Kafka只提供分割槽中的記錄的總的順序,而不保證分割槽之間的順序。
Guarantees
一個高階別的kafka給出下列保證:
- 生產者傳送到topic分割槽的訊息是按照它們被髮送的順序追加的。因此,如果記錄M1和M2都是被同一個生產者傳送的,並且M1在前M2在後,那麼M1在分割槽中的偏移量將比M2小,而且M1的日誌也在M2的前面。
- 一個消費者例項看到記錄的順序是按照記錄儲存在日誌中的順序的
- 假設topic的副本因子是N,那麼我們可以容忍N-1個服務失敗,也不會丟失任何的提交日誌
Kafka as a Messaging System
訊息傳統上有兩種模型:queuing 和 publish-subscribe(點對點佇列模型和釋出訂閱模型)。在佇列模型中,每個訊息只能被消費一次;在釋出訂閱模型中,訊息可以廣播給所有的消費者。這兩種模型各有利弊。
Kafka中的消費者分組的概念就是在從這兩種模型中衍生出來的。和佇列模型一些,消費者分組允許你在處理集合之上分開處理。和釋出訂閱模型一樣,kafka允許你廣播訊息給多個消費者分組。
Kafka的模型的優勢在於它的每個topic有這樣一些屬性:它可以伸縮處理,而且它有多個訂閱者
相對於傳統的訊息系統而言,Kakfa有更強的順序保證。
傳統的佇列在伺服器上按順序儲存記錄,而且多個消費者從佇列中消費記錄是按照記錄被儲存的順序來消費的。雖然伺服器是按順序處理記錄的,但是記錄是非同步投遞給消費者的,所以它們可能以不同的順序到達消費者。也就是說,在並行消費的時候會丟失一定百分比的順序。訊息系統中一個概念叫"exclusive consumer"它允許只能有一個消費者來處理,也就意味著是序列處理。
Kafka做得更好。它有一個概念叫“parallelism—the partition—within the topics”(在topics的分割槽下的並行)。kafka既保證順序同時還提供負載均衡。這一切都歸功於給消費者分組中的消費者指定topic的分割槽,以至於每個分割槽都可以被一個消費者精確的消費。注意分組中的消費者數量不能比分割槽數還多。
Kafka as a Storage System
任何訊息佇列都允許釋出訊息和消費訊息解耦,在這個過程中扮演一個儲存系統的角色。寫到kafka的資料被寫到磁碟並且被複制。kafka允許生產者等待確認,以至於只有當資料被完全複製並且保證已經被持久化了才能認為這個寫操作是完成的。
不管你是持久化50KB還是50TB的資料,kakfa執行的操作都是一樣的。
你可以把kafka當做一種特別的分散式檔案系統,它高效能、低延遲的提交日誌儲存、副本。
Kafka for Stream Processing
僅僅只是讀寫儲存流資料是不夠的,要能夠實時處理流。
kafka的流處理器是從輸入topic那裡持續不斷的接收流,然後對這些輸入做一些處理,並且生成持續不斷的流資料到輸出topic。
例如,一個零售應用可能採集銷售和物流的的資料作為輸入流,然後基於這些資料進行計算,從而生成再次訂購和價格調整的輸出流。
參考 http://kafka.apache.org/intro
本節重點
1、kafka是一個分散式的流平臺
2、kafka有什麼用?
- 構建實時的流資料管道
- 構建實時的流應用
3、基本概念
- kafka是以叢集方式執行的,叢集可以是一臺或者多臺伺服器
- 記錄按照類別來儲存,這些類別叫topics。可以簡單的理解為,資料儲存在topics中
- 每條記錄由key、value、timestamp組成
4、核心API
- Producer:生產者,釋出記錄(訊息)到一個或多個topics中
- Consumer:消費者,訂閱一個或者多個topics
- Streams:流處理器,從一個或多個topics那裡消費輸入流並且生成輸出流到一個或多個topics
- Connector:構建可以連線到外部的應用或者資料系統的可重用的生產者或消費者
5、主題和日誌
5.1、一個主題就是一個分類,記錄被髮布到某個主題中,主題總是有多個訂閱者,一個主題可以有0個或1個或多個消費者
5.2、每個主題都有一個分割槽日誌。每個分割槽都是一個有序的、不可變的記錄序列,記錄被持續不斷的追加到分割槽中
5.3、記錄是一個結構化的提交日誌(a structured commit log)
5.4、分割槽中的每條記錄都被指定了一個唯一的id號,叫做offset。offset是由消費者控制的。
5.5、kafka儲存所有已釋出的記錄,不管它們是不是已經被消費。保留的週期是可配置的。
5.6、為什麼要分割槽呢?分割槽可以突破單臺伺服器的限制。
6、分佈
6.1、日誌分割槽被分佈在叢集中的伺服器之上,這些分割槽之下的每個伺服器處理資料和請求的時候共享此分割槽,每個分割槽會被複制到其它伺服器上,副本的數量可配置。
6.2、每個分割槽中,有一個伺服器充當"leader"的角色,有0個或者多個充當"follower"的角色。leader負責處理所有讀寫請求,而follower被動的從leader那裡複製。如果leader死了,其中一個follower會自動成為leader。一個伺服器可能是它所在的那些分割槽的其中一個分割槽的leader的同時也可能是其它分割槽的follower。(PS:這段話的意思是,一個分割槽可能有1臺或者多臺伺服器組成,在組成個分割槽的伺服器中有一個伺服器是leader角色,其餘是follower角色,leader角色負責這個分割槽的所有讀寫操作,而follower則被動的從leader那裡複製資料。而且,一個伺服器可能在這個分割槽的leader,但同時也可能是別的分割槽的follower。)
7、生產者
生產者負責指定記錄釋出到哪個topic的哪個分割槽中
8、消費者
8.1、消費者用消費者組名來標記它們自己,每個消費者分組都是topics的一個邏輯訂閱者
8.2、被髮布到topics中的每一條記錄會被投遞到每個訂閱的消費者分組中的一個消費例項
8.3、每個消費者分組由多個消費者例項組成,而且例項的數量是可伸縮的
9、保證
- 同一個消費者傳送的同一個topic同一個分割槽中的訊息會按照它們傳送的順序依次追加。假設M1和M2都是由同一個分割槽傳送的訊息,而且M1先被髮送,那麼M1的offset必定比M2小
- 消費者是按照訊息儲存的順序看到訊息的
- 假設副本因子是N,那麼即使有N-1個伺服器掛了也不會丟失任何記錄
10、kafka作為訊息系統
10.1、topics中的每條記錄只會被投遞到每個訂閱的消費者分組中的一個消費者例項。也就是說,假設有2個消費者分組都訂閱了這個topics,並且每個分組都有3個消費者例項,那麼這個topics中的每條記錄只會投遞2份分別給這兩個分組,每個分組收到這條記錄以後只能由該分組中的一個消費者例項消費。
10.2、基於第一點,那麼,如果訂閱這個topics的所有消費者都屬於同一個分組,那麼這就相當於點對點佇列模型;如果訂閱的所有消費者都屬於不同的消費者分組,那麼這就相當於是釋出訂閱模型。
10.3、kafka保證同一個生產者傳送到同一個topics下的同一個分割槽的訊息的儲存順序和它們傳送的順序一致,而且消費這個分割槽的消費者看到訊息的順序和它們儲存的順序是一樣的。
10.4、主題下分割槽中並行,kafka既保證順序又能夠負載均衡。這一切都歸功於指定分割槽到分組中的消費者,以至於每個分割槽只能被消費者分組中的一個消費者消費。通過這樣做,就可以確保消費者只能按順序消費資料。
11、兩張很重要的圖