1. 程式人生 > >Kafka學習筆記(3)----Kafka的資料複製(Replica)

Kafka學習筆記(3)----Kafka的資料複製(Replica)

1. CAP理論

  1.1 Cosistency(一致性)

  通過某個節點的寫操作結果對後面通過其他節點的讀操作可見。

  如果更新資料後,併發訪問的情況下可立即感知該更新,稱為強一致性

  如果允許之後部分或全部感知不到該更新,稱為弱一致性。

  若在之後的一段時間(通常該時間不是固定的)後,一定可以感知到該更新,稱為最終一致性。

  1.2 Availability(高可用性)

  即是任何一個沒有發生故障的節點必須在有限的時間內返回合理的結果(不論是正確的還是錯誤的)。

  1.3 Partition tolerance(分割槽容錯性)

  部分節點宕機或者是無法與其他節點通訊時,各分割槽間還可以保持分部式系統的功能,比如上海和北京兩個網路分割槽,當上海分割槽光纖或其他原因導致網路不通時,北京上海兩個分割槽之間不可通訊,但是最起碼要保證北京的分割槽中的分散式系統功能可用。

  1.4 CAP理論

  分散式系統中,一致性,可用性,分割槽容忍性最多隻可同時滿足兩個,但是一般分割槽容錯性都是需要保障的,因此很多時候都是在可用性和一致性之間做權衡。如下一幅圖講解了CP和AP的兩種模式的具體表現形式:

 

  首先看CP模式,N1和N2之間代表了網路通訊,C表示客戶端,X表示新寫入的資料,Y表示舊資料,當C向N2發起請求時,由於N2與N1之間網路通訊異常,會導致N2不能同步到N1中的x,在保證一致性的情況下,此時N2不會正常返回處理結果,要麼是等待網路連線成功,將N1的Y獲取過來,保證資料一致,要麼系統出現錯誤,這樣的情況是不能保證高可用的,但是保證了資料一致性。

  AP模式下,N1和N2之間代表了網路通訊,C表示客戶端,X表示新寫入的資料,Y表示舊資料,當C向N2發起請求時,由於N2與N1之間網路通訊異常,會導致N2不能同步到N1中的X,但是N2不會等待N1連線成功,或是返回錯誤資訊,而是返回之前老的資料x,這樣系統能夠正常的執行,但是資料的一致性並沒有保證,此時選擇了系統的高可用方案。

  1.5 一致性的方案

  1.5.1 Master-slave(主從模式)

  RDBMS的讀寫分離即為典型的Master-slave方案

  同步複製可保證強一隻性,但是會行影響效能(因為Master必須要等待所有的salve都接收到到更新才能返回)

  非同步複製提高可用性,但是會降低一致性,因為Master只需要自己寫操作完成,就立即返回,同時向Slave進行復制,這期間可能會出現某個或多個Slave由於網路或其他原因沒有更新到資料,造成資料不一致性。

  1.5.2 WNR

  主要用於去中心化(P2P)的分散式系統中。DynamoDB與Cassandra即採用此方案,N代表副本數,W代表每次寫操作要保證的最少寫成功的副本數,R代表每次讀至少讀取的副本數,當W+R>N時,可保證每次讀取的資料至少有一個副本具有最新的更新,多個寫操作的順序難以保證,可能導致多副本間的寫操作順序不一致,Dynamo通過向量時鐘保證最終一致性。這裡可以通過時間戳或者是自增主鍵之類的方式來保證過濾出讀取的最新的資料。

  1.5.3 Paxos及其變種

  Google的Chubby,Zookeeper的Zab,RAFT等

2. Kafka的資料複製(Replica)

  Kafka提供了Replica保證了資料一致性

  2.1 Replica

  當某個Topic的replication-factor為N切N大於1時,每個Partition都會有N個副本(Replica),Replica的個數小於等於Broker數,即對每個Partition而言每個Broker上只會有一個Replica,因此可用Broker ID表示Replica,所有Partition的所有Replica預設情況會均勻分佈到所有Broker上,如圖:

  圖中可以看到,Broker中存的是Topic2的Partition0和Topic2的Partition2的Replica,但是在Broker2中卻存了Topic2的Partition1和Topic2的Partition0的Replica,所以預設的Partition都是分佈在叢集節點上的,replica也一樣。這就可以保證到某個節點掛掉之後,其他的節點中儲存的replica仍然可以向消費者推送或被拉取訊息,保證訊息不丟失。

  注意:

  假如當前我們搭建了三個Broker的叢集,但是我此時指定4個Replica時,會出現org.apache.kafka.common.errors.InvalidReplicationFactorException: Replication factor: 4 larger than available brokers: 3異常,如圖:

 2.2 Data Replication(資料複製)要解決的問題

  2.2.1 如何Propagate(備份)訊息

  如下圖:

  當producer想leader節點發送訊息時,其餘follower節點(個人理解跟slave類似)將會如其他mq的consumer一樣去從主節點的topic中將資料拉取或被推送到自身節點中。這樣當leader節點掛掉之後,consumer訪問叢集時,仍然可以從其他的follower中獲取到最新資料,防止了資料丟失。

  2.2.2 何時Commit

  ISR: Leader會維護一個與其基本保持同步的Replica列表,該列表稱為ISR(in-sync Replica),如果一個Follower比Leader落後太多,或者超過一定時間未發起資料複製請求,則Leader將其從ISR中移除,當ISR中所有Replica都向Leader傳送ACK時,Leader即Commit(告訴Producer訊息傳送成功)。

  Commit策略

  1. 在Server中配置

  replica.lag.time.max.ms:預設100000,最大未發起資料複製請求的時間。

  replica.lag.max.messages:最大落後訊息數,根據自身需要配置

  2. Topic配置

  min.insync.replicas=1: ISR列表最小個數,預設1,只有當request.required.acks為-1時才生效,如果ISR中的副本數少於min.insync.replicas配置的數量時,客戶端會返回異常:org.apache.kafka.common.errors.NotEnoughReplicasExceptoin: Messages are rejected since there are fewer in-sync replicas than required。

  3. Produce配置

  request.required.acks=1,預設為1,roducer傳送資料到leader,leader寫本地日誌成功,返回客戶端成功;此時ISR中的副本還沒有來得及拉取該訊息,leader就宕機了,那麼此次傳送的訊息就會丟失,當為-1時,當producer設定request.required.acks為-1時,min.insync.replicas指定replicas的最小數目(必須確認每一個repica的寫資料都是成功的),如果這個數目沒有達到,producer會產生異常。

  2.2.3 如何處理Replica恢復

  如圖:

 

  1. 可以看到SR={A,B,C},Leader(A)節點中存在m1,m2,m3三條訊息,F(B)存在m1,m2兩條訊息,f(c)只存在m1一訊息,所以這裡只會提交m1這條訊息,因為m2這條訊息還沒有在ISR中完成複製。它只會提交三個ISR中都存在的訊息。

  2. 當L(A)在將訊息m2複製到B,C之後掛掉,此時ISR中只有{B,C},B被選舉成為新的主節點,當m2,m1都存在於B,C節點中時,B將會提交m1,m2兩條訊息,不會提交m3訊息。

  3. 此時訊息將都會發送到B節點上,C節點同步了B節點中的新發的訊息m4,m5之後,將會提交m4,m5.

  5.此時A節點連線叢集成功或重啟,可以使用了,它會從B節點中同步從m1,到m5的訊息,直到它的訊息與B和C中的一致為止,此時的Replica將會變成ISR={A,B,C},完成了Replica的恢復。這裡我們發現m3並沒有存在了,這裡並不是丟失了,只是當沒有主節點提交m3這條訊息時,它將會自動反饋到Producer,Producer會重試,或做其他處理,當重試成功後可能m3訊息將會append到m5的後面,所以consumer消費訊息時,我們保證的順序性不是producer傳送訊息的順序,而是commit時的順序。

  2.2.4 如何處理Replica全部宕機

  當ISR中的Replica全部宕機時,可以通過如下方式處理:

  1. 等待ISR中任一Replica恢復,並選它為Leader。

  缺點:等待時間較長,降低可用性(因為不能使用所有叢集節點),因此或ISR中的所有Replica都無法恢復或者資料丟失,則該Partition將永不可用。

  2. 選擇第一個恢復的Replica為新的Leader,無論它是否在ISR中。

  缺點:並未包含所有已被之前Leader Commit過的訊息(因為它不在之前的ISR中),因此會造成資料丟失,但是它提高了可用節點的範圍,可用性比較高。