配置Apache Kafka生產者引數以獲得高可用性和彈性 - Nabraj

banq發表於2021-11-19

Apache kafka以其彈性、容錯性和高吞吐量而聞名。但它的表現並不總是滿足所有人的期望。在某些情況下,我們可以通過縮小或擴大代理規模來改進它。而在大多數情況下,我們必須玩配置遊戲。

在卡夫卡的生態系統中,確實有很多配置。幾乎不可能掌握每個配置的概念。一方面,它們確實使系統更加靈活,但另一方面,開發人員可能會對如何使用它們感到困惑。

幸運的是,大多數配置都是預定義的,它們在大多數情況下都能很好地工作。首先,他們需要知道的強制性配置非常有限。

當然,我想你讀這篇文章是因為你想把卡夫卡製作人帶到一個新的層次。因此,在本文中,我想分享10種配置,我認為這些配置對於使您的生產商更具彈性非常重要。

本文討論的kafka配置引數:

acks
replica.lag.time.max.ms
min.insync.replicas
retries
enable.idempotent
max.in.flight.requests.per.connection
buffer.memory
max.block.ms
linger.ms
batch.size

 

ACK

ack是生產者從Kafka代理獲得的確認,以確保訊息已成功提交給該代理。  引數acks是生產者在考慮成功提交之前需要接收的多少次確認?

配置Apache Kafka生產者引數以獲得高可用性和彈性 - Nabraj

圖中是ack=1 和ack=all的區別

ack預設值為1,這意味著只要生產者從該主題的leader broker接收到ack,它就會將其視為成功提交併繼續執行下一條訊息。不建議將acks設定為0,因為這樣您就無法保證提交。acks=all將確保生產者從該主題的所有同步副本獲取ACK。它提供了最強的訊息永續性,但也需要較長的時間,從而導致更高的延遲。所以,你需要決定什麼對你更重要。

 

In-sync replicas

acks=all將從所有同步副本(ISR)獲得確認,那麼什麼是同步副本?建立主題時,必須定義所需的副本數量。副本只不過是其中一個代理中訊息的副本,因此副本的最大數量是代理的數量。

在這些複製副本中,有一個領導者,其餘的都是追隨者。領導者處理所有讀寫請求,而追隨者被動地複製領導者。同步副本是指在最後10秒內完全趕上領先者的副本。可以通過replica.lag.time.max.ms配置時間段。如果某個代理主機當機或出現網路問題,則該代理無法跟進領導者主機節點,10秒後,該代理將從ISR中刪除。

預設的最小同步副本(min.insync.replicas)為1。這意味著,如果所有的追隨者都倒下了,那麼ISR只包括領導者。即使acks設定為all,它實際上也只將訊息提交給1個代理(leader),這會使訊息易受攻擊。

配置Apache Kafka生產者引數以獲得高可用性和彈性 - Nabraj

圖中是不同min.insync.replicas引數得區別

config min.insync.replicas基本上定義了生產者在考慮成功提交之前必須接收的副本數量。此配置將新增到acks=all之上,使您的訊息更安全。但另一方面,您必須平衡延遲和速度。

 

Retry on failure

假設您設定了acks=all和min.insync.replicas=2。出於某種原因,跟隨者完成了,然後生產者識別出一個失敗的提交,因為它無法從min.insync.replications代理獲取ACK。

您將從生產者處收到一條錯誤訊息:

KafkaError{code=NOT_ENOUGH_REPLICAS,val=19,str="Broker: Not enough in-sync replicas"}

您將看到來自正在執行的代理的以下錯誤訊息。這意味著,即使代理正在執行,如果當前ISR不足,Kafka也不會將訊息追加到正在執行的代理。

ERROR [ReplicaManager broker=0] Error processing append operation on partition test-2-2-0 (kafka.server.ReplicaManager)
org.apache.kafka.common.errors.NotEnoughReplicasException: The size of the current ISR Set(0) is insufficient to satisfy the min.isr requirement of 2 for partition test-2-2-0

預設情況下,生產者不會對此錯誤採取行動,因此將丟失訊息。這就是“最多隻能呼叫一次”語義。但是您可以通過配置retries=n讓生產者重新傳送訊息。這基本上是生產者在提交失敗時的最大重試次數。預設值為0。

配置Apache Kafka生產者引數以獲得高可用性和彈性 - Nabraj

圖是retries=0 和 retries>0區別 

如果您將retries設定為5,則生產者最多將重試5次。您不會注意到生產者日誌中的重試次數,因為它只顯示提交是否成功。但是您可以在代理端看到retries+1日誌訊息。

 

避免重複訊息 

在某些情況下,訊息實際上已提交給所有同步副本,但由於網路問題,代理無法傳送回ack(例如,僅允許單向通訊)。同時,我們將retries設定為3,那麼生產者將重新傳送訊息3次。這可能會導致主題中出現重複訊息。

假設我們有一個生產者向主題傳送1M條訊息,而代理在訊息提交後但生產者收到所有ACK之前失敗。在這種情況下,我們可能會收到超過100萬條關於這個主題的資訊。這也稱為至少一次語義。

最理想的情況是一次語義,即即使生產者重新傳送訊息,消費者也只能收到同一訊息一次。

我們需要的是一個冪等生產者。冪等式意味著一次或多次應用一個運算具有相同的效果。使用config enable.idempotent=true很容易啟用此功能。

它是如何工作的?訊息分批傳送,每批都有一個序列號。在代理端,它跟蹤每個分割槽的最大序列號。如果有一個序列號較小或相等的批進入,代理將不會將該批寫入主題。這樣,它還可以確保批次的順序。

配置Apache Kafka生產者引數以獲得高可用性和彈性 - Nabraj

上圖展示啟用冪等和失效冪等得區別

 

按順序傳送訊息

確保順序的另一個重要配置是max.in.flight.requests.per.connection,預設值為5。這表示可以在生產者端緩衝的未確認請求的數量。如果重試次數大於1且第一個請求失敗,但第二個請求成功,則第一個請求將重新傳送,訊息的傳送順序將變錯誤了。

根據文件說明:

請注意,如果此設定設定為大於1,並且存在傳送失敗的情況,則存在由於重試而導致訊息重新排序的風險(即,如果啟用了重試)。

如果不啟用冪等項,但仍希望保持訊息的有序,則應將此設定配置為1。

但如果已經啟用了冪等項,則不需要顯式定義此配置。卡夫卡將選擇合適的值,如本文所述。

如果使用者未明確設定這些值,將選擇合適的值。如果設定了不相容的值,將引發ConfigException。

 

訊息傳送得太快

當生產者呼叫send()時,訊息不會立即傳送,而是新增到內部緩衝區。預設的buffer.memory是32MB。如果生產者傳送訊息的速度快於它們傳輸到代理的速度,或者存在網路問題,則訊息將超過buffer.memory,那麼send()呼叫將被阻塞到max.block.ms(預設為1分鐘)。

可以通過增加這兩個值buffer.memory和max.block.ms來緩解此問題。

另外兩個可以使用的配置是linger.ms和batch.size。linger.ms是批次準備好傳送之前的延遲時間。預設值為0,這意味著即使批中只有1條訊息,也會立即傳送批。有時,人們會增加linger.ms以減少請求數量並提高吞吐量。但這將導致更多的資訊儲存在記憶體中。所以,一定要照顧好雙方。

有一個與linger.ms等效的配置,即batch.size。這是單個批次的最大尺寸。當滿足這兩個要求中的任何一個時,將傳送批次。

 

相關文章