再說複製
Kafka 的複製機制和分區的多副本架構是Kafka 可靠性保證的核心。把消息寫入多個副本可使Kafka 在發生崩憤時仍能保證消息的持久性。
Kafka 的主題被分爲多個分區,分區是基本的數據塊。分區存儲在單個磁盤上,Kafka 能夠保證分區裏的事件是有序的,分區能夠在線(可用),也能夠離線(不可用) 。每一個分區能夠有多個副本,其中一個副本是首領。全部的事件都直接發送給首領副本,或者直接從首領副本讀取事件。其餘副本只須要與首領保持同步,並及時複製最新的事件。當首領副本不可用時,其中一個同步副本將成爲新首領。
分區首領是同步副本,而對於跟隨者副原本說,它須要知足如下條件才能被認爲是同步的。
網絡
若是跟隨者副本不能知足以上任何一點,好比與Zookeeper 斷開鏈接,或者再也不獲取新消息,或者獲取消息滯後了10s 以上,那麼它就被認爲是不一樣步的。一個不一樣步的副本經過與Zookeeper 從新創建鏈接,並從首領那裏獲取最新消息,能夠從新變成同步的。這個過程在網絡出現臨時問題並很快獲得修復的狀況下會很快完成,但若是broker 發生崩憤就須要較長的時間。架構
broker 有3 個配置參數會影響Kafka 消息存儲的可靠性。與其餘配置參數同樣,它們能夠應用在broker 級別,用於控制全部主題的行爲,也能夠應用在主題級別,用於控制個別主題的行爲。在主題級別控制可靠性,意味着Kafka 集羣能夠同時擁有可靠的主題和非可靠的主題。例如,在銀行裏,管理員可能把整個集羣設置爲可靠的,但把其中的一個主題設置爲非可靠的,用於保存來自客戶的投訴,由於這些消息是容許丟失的。spa
複製係數
主題級別的配置參數是replication.factor,而在broker 級別則能夠經過default.replication.factor來配置自動建立的主題。
若是複製係數爲N,那麼在凡l 個broker 失效的狀況下,仍然可以從主題讀取數據或向主題寫入數據。因此,更高的複製係數會帶來更高的可用性、可靠性和更少的故障。另外一方面,複製係數N 須要至少N 個broker ,並且會有N 個數據副本,也就是說它們會佔用N倍的磁盤空間。咱們通常會在可用性和存儲硬件之間做出權衡。
建議在可用性的場景下,把複製係數設置爲3.線程
不徹底的首領選舉code
以前提到過,當分區首領不可用時,一個同步副本會被選舉爲新首領。若是在選舉過程當中沒有丟失數據,也就是說提交的數據同時存在於全部的同步副本上,那麼這個選舉就是「徹底的」
但若是在首領不可用時其餘副本都是不一樣步的,咱們該怎麼辦呢?blog
#如下兩種狀況:
第一種: 分區有3 個副本,其中的兩個跟隨者副本不可用(好比有兩個broker 發生崩憤)。這個時候,若是生產者繼續往首領寫入數據,全部消息都會獲得確認井被提交(由於此時首 領是惟一的同步副本)。如今咱們假設首領也不可用了(又一個broker 發生崩憤),這個時候,若是以前的一個跟隨者從新啓動,它就成爲了分區的惟一不一樣步副本。 第二種: 分區有3 個副本,由於網絡問題致使兩個跟隨者副本複製消息滯後,因此儘管它複製消息,但已經不一樣步了。首領做爲惟一的同步副本繼續接收消息。這個時候,若是 首領變爲不可用,另外兩個副本就再也沒法變成同步的了。
#上面這兩種狀況該如何解決?
第一種:要麼等待原首領復活,可是等待過程當中服務是宕的,有可能這是一個很長的時間段;要麼使用新的首領,可是確定丟失了數據。
第二種:由於兩個副本已經滯後了,因此若首領不可用,那麼滯後的同步副本被選爲新首領,就會形成數據丟失的問題(數據不一致)。
簡而言之,若是咱們容許不一樣步的副本成爲首領,那麼就要承擔丟失數據和出現數據不一致的風險。若是不容許它們成爲首領,那麼就要接受較低的可用性,由於咱們必須等待原先的首領恢復到可用狀態。
若是把unclean.leader.election.enable 設爲true ,就是容許不一樣步的副本成爲首領(也就是「 不徹底的選舉"),那麼咱們將面臨丟失消息的風險。若是把這個參數設爲false ,
就要等待原先的首領從新上線,從而下降了可用性。咱們常常看到一些對數據質量和數據一致性要求較高的系統會禁用這種不徹底的首領選舉( 把這個參數設爲false ) 。銀行系統是這方面最好的例子,大部分銀行系統寧願選擇在幾分鐘甚至幾個小時內不處理信用卡支付事務,也不會冒險處理錯誤的消息。不過在對可用性要求較高的系統裏,好比實時點擊流分析系統, 通常會啓用不徹底的首領選舉。事件
最少同步副本事務
在主題級別和broker 級別上,這個參數都叫min.insync.replicas 。咱們知道,儘管爲一個主題配置了3 個副本,仍是會出現只有一個同步副本的狀況。若是這個同步副本變爲不可用,咱們必須在可用性和一致性之間做出選擇一一這是一個兩難的選擇。根據Kafka 對可靠性保證的定義,消息只有在被寫入到全部同步副本以後才被認爲
是已提交的。但若是這裏的「全部副本」只包含一個同步副本,那麼在這個副本變爲不可用時,數據就會丟失。開發
若是要確保已提交的數據被寫入不止一個副本,就須要把最少同步副本數量設置爲大一點的值。對於一個包含3 個副本的主題,若是min.insync.replicas被設爲2 ,那麼至少要存在兩個同步副本才能向分區寫入數據。同步
若是3 個副本都是同步的,或者其中一個副本變爲不可用,都不會有什麼問題。不過,若是有兩個副本變爲不可用,那麼broker 就會中止接受生產者的請求。嘗試發送數據的生產者會收到NotEnoughReplicasException 異常。消費者仍然能夠繼續讀取已有的數據。實際上,若是使用這樣的配置,那麼當只剩下一個同步副本時,它就變成只讀了,這是爲了不在發生不徹底選舉時數據的寫入和讀取出現非預期的行爲。爲了從只讀狀態中恢復,必須讓兩個不可用分區中的一個從新變爲可用的(好比重啓broker),並等待它變爲同步的。
配置重試參數
以下的一個實例:
爲broker 配置了3 個副本,而且禁用了不徹底首領選舉。 把生產者的acks 設爲all 。假設如今往Kafka 發送消息,分區的首領恰好崩憤,新的首領正在選舉當中, Kafka 會向生產者
返回「首領不可用」的響應。在這個時候,若是生產者沒能正確處理這個錯誤,也沒有重試發送消息直到發送成功,那麼消息也有可能丟失。這算不上是broker 的可靠性問題,由於broker
並無收到這個消息。這也不是一致性問題,由於消費者井沒有讀到這個消息。問題在於若是生產者沒能正確處理這些錯誤,弄丟消息的是它們本身。
#解決這個問題,生產者再發一次消息就能夠了!
生產者須要處理的錯誤包括兩部分: 一部分是生產者能夠自動處理的錯誤,還有一部分是須要開發者手動處理的錯誤。
若是broker 返回的錯誤能夠經過重試來解決,那麼生產者會自動處理這些錯誤。生產者向broker 發送消息時, broker 能夠返回一個成功晌應碼或者一個錯誤響應碼。錯民晌應碼能夠分爲兩種, 一種是在重試以後能夠解決的,還有一種是沒法經過重試解決的。例如,若是broker 返回的是LEADER_NOT_AVAILABLE 錯誤,生產者能夠嘗試從新發送消息。也許在這個時候一個新的首領被選舉出來了,那麼此次發送就會成功。也就是說, LEADER_NOT_AVAILABLE是一個可重試錯誤。另外一方面,若是broker 返回的是INVALID_CONFIG 錯誤,即便經過重試也無能改變配置選項,因此這樣的重試是沒有意義的。這種錯誤是不可重試錯誤。
上面提到的是生成者的一些配置,下面咱們來講明消費者的一些配置。
下面這段着重理解一下:
只有那些被提交到Kafka 的數據,也就是那些已經被寫入全部同步副本的數據,對消費者是可用的,這意味着消費者獲得的消息已經具有了一致性。消費者惟一要作的是跟蹤哪些消息是已經讀取過的,哪些是尚未讀取過的。這是在讀取消息時不丟失悄息的關鍵。
在從分區讀取數據時,消費者會獲取一批事件,檢查這批事件裏最大的偏移量,而後從這個偏移量開始讀取另一批事件。這樣能夠保證消費者總能以正確的順序獲取新數據, 不會錯過任何事件。
若是一個悄費者退出,另外一個消費者須要知道從什麼地方開始繼續處理,它須要知道前一個消費者在退出前處理的最後一個偏移量是多少。所謂的「另外一個」消費者,也可能就是它本身重啓以後從新回來工做。這也就是爲何消費者要「提交」它們的偏移量。它們把當前讀取的偏移量保存起來,在退出以後,同一個羣組裏的其餘消費者就能夠接孚它們的工做。若是消費者提交了偏移量卻未能處理完消息,那麼就有可能形成消息丟失,這也是消費者丟失消息的主要緣由。在這種狀況下,若是其餘消費者接手了工做,那些沒有被處理完的消息就會被忽略,永遠得不處處理。這就是爲何咱們爲何很是重視偏移量提交的時間點和提交的方式。
#已提交的消息與已提交的偏移量
此處的己提交消息與以前討論過的已提交消息是不同的,它是指已經被寫入全部同步副本而且對消費者可見的消息,而己提交偏移量是指消費者發送給Kafka 的偏移量,
用於確認它已經收到並處理好的消息位置。
這裏僅說明四個比較重要參數的配置