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、兩張很重要的圖