使用Scala開發Apache Kafka的TOP 20大最佳實踐!

趙鈺瑩發表於2018-08-23

本文作者是一位軟體工程師,他對20位開發人員和資料科學家使用Apache Kafka的方式進行了最大限度得深入研究,最終將生產實踐環節需要注意的問題總結為本文所列的20條建議。 

Apache Kafka是一個廣受歡迎的分散式流媒體平臺,New Relic、Uber以及Square等數千家公司都在使用它構建可擴充套件、高吞吐量、可靠的實時流媒體系統。例如,New Relic的Kafka叢集每秒處理超過1500萬條訊息,總資料速率接近1 Tbps。

Kafka在應用程式開發人員和資料科學家中非常受歡迎,因為它極大簡化了資料流的處理過程。但是,Kafka在Scala上實踐會比較複雜。如果消費者無法跟上資料流,並且訊息在他們看到之前就消失了,那麼具有自動資料保留限制的高吞吐量釋出/訂閱模式並沒有多大用。同樣,如果託管資料流的系統無法擴充套件以滿足需求或者不可靠,也沒有什麼用。

為了降低這種複雜性,作者將可能的問題分為4大類共20條,以方便使用者理解:

  • Partitions(分割槽)

  • Consumers(消費者)

  • Producers(生產者)

  • Brokers

Kafka是一種高效分散式訊息傳遞系統,可提供內建資料冗餘和彈性,同時保留高吞吐量和可擴充套件性。它包括自動資料保留限制,使其非常適合將資料視為流的應用程式,並且還支援對鍵值對對映建模的“壓縮”流。

瞭解最佳實踐之前,你需要熟悉一些關鍵術語:

  • Message訊息:Kafka中的記錄或資料單元。每條訊息都有一個鍵(key)和一個值(value),以及可選標題。

  • 生產者:生產者向Kafka的topic釋出訊息。生產者決定要釋出哪個topic分割槽,可以隨機(迴圈)或使用基於訊息金鑰的分割槽演算法。

  • Broker:Kafka在分散式系統或叢集中執行,叢集中的每個節點都稱為broker。

  • Topic:Topic是釋出資料記錄或訊息的類別。消費者訂閱topic以讀取寫入其中的資料。

  • Topic partition:topic分為多個分割槽,每個訊息都有一個偏移量。每個分割槽通常至少複製一或兩次。每個分割槽都有一個leader和至少一個副本(資料副本),這些副本存在於follower身上,可以防止broker失敗。叢集中的所有broker都是leader和follower,但是代理最多隻有一個topic partition副本,leader用於所有讀寫操作。

  • 偏移:為分割槽內的每條訊息分配一個偏移量,這是一個單調遞增整數,用作分割槽內訊息的唯一識別符號。

  • 消費者:消費者通過訂閱 topic partition讀取Kafka主題的訊息,消費應用程式,並處理訊息以完成所需工作。

  • Consumer group:消費者可以組織成消費者群組,分配topic partition以平衡組中所有使用者。在消費者群組中,所有消費者都在負載均衡模式下工作。換句話說,組中每個消費者都將看到每條訊息。如果一個消費者離開,則將該分割槽分配給該組中的其他消費者,這個過程稱為再平衡。如果組中的消費者多於分割槽,則一些消費者將閒置。如果組中的消費者少於分割槽,則某些消費者將使用來自多個分割槽的訊息。

  • Lag:當消費者無法從分割槽中讀取訊息,消費者就會出現Lag,表示為分割槽頂部後的偏移數。從Lag狀態恢復所需的時間取決於消費者每秒消耗訊息的速度:

time = messages / (consume rate per second - produce rate per second)

第一部分:使用分割槽的最佳實踐!

在分割槽部分,我們需要了解分割槽的資料速率,以確保擁有正確的保留空間。分割槽的資料速率是生成資料的速率。換句話說,它是平均訊息大小乘以每秒訊息數。資料速率決定了給定時間內所需的保留空間(以位元組為單位)。如果不知道資料速率,則無法正確計算滿足基本保留目標所需的空間大小。資料速率指定了單個消費者需要支援的最低效能而保證不會出現Lag。

除非有其他架構需求,否則在寫入topic時使用隨機分割槽。當進行大規模操作時,分割槽之間的資料速率不均可能難以管理。需要注意以下三方面:

1、首先,“熱點”(更高吞吐量)分割槽的消費者必須處理比消費者群組中其他消費者更多的訊息,這可能導致處理和網路瓶頸。

2、其次,必須為具有最高資料速率的分割槽調整topic保留空間大小,這可能會導致topic中其他分割槽的磁碟使用量增加。

3、最後,在分割槽領導方面實現最佳平衡比簡單地擴充套件到所有 brokers更復雜。“熱點”分割槽的份量可能是同一topic中另一分割槽的10倍。

第二部分:使用消費者最佳實踐!

如果消費者執行的Kafka版本低於0.10,請升級。在0.8.x版本中,消費者使用Apache ZooKeeper進行消費者群組協調,並且許多已知錯誤可能導致長期執行的平衡甚至是重新平衡演算法的失敗(我們稱之為“重新平衡風暴”)。在重新平衡期間,將一個或多個分割槽分配給使用者群組中的每個使用者。在再平衡中,分割槽所有權在消費者中不斷變通,阻止任何消費者在消費方面取得實際進展。

4、調整消費者套接字緩衝區以進行高速獲取。在Kafka 0.10.x中,引數為isreceive.buffer.bytes,預設為64kB。在Kafka 0.8.x中,引數是socket.receive.buffer.bytes,預設為100kB。對於高吞吐量環境,這兩個預設值都太小,特別是如果brocker和消費者之間的網路頻寬延遲大於區域網(LAN)。對於延遲為1毫秒或更長的高頻寬網路(10 Gbps或更高),請考慮將套接字緩衝區設定為8或16 MB。如果記憶體不足,請考慮1 MB,也可以使用值-1,這樣底層作業系統可以根據網路條件調整緩衝區大小。但是,對於需要啟動“熱點”消費者的系統而言,自動調整的速度可能或比較慢。

5、設計高吞吐量消費者,以便在有保證的情況下實施背壓,最好只消耗可以有效處理的東西,而不是消耗太多,以至於過程停止,退出消費者群組。 消費者應該使用固定大小的緩衝區(參見Disruptor模式),如果在Java虛擬機器(JVM)中執行,最好是在堆外使用。固定大小的緩衝區將阻止消費者將大量資料拖到堆上,JVM花費所有時間來執行垃圾收集而不是做你想讓它處理的工作——處理訊息。

6、在JVM上執行消費者時,請注意垃圾回收可能對消費者產生的影響。例如,垃圾收集較長時間暫停可能導致ZooKeeper會話或者消費者組失去平衡。對於brocker來說也是如此,如果垃圾收集暫停時間過長,則可能會從叢集中退出。

第三部分:使用生產者最佳實踐!

7、配置生產者等待確認。 這就是生產者如何知道訊息實際已經傳送到brocker上的分割槽。在Kafka 0.10.x中,設定為acks; 在0.8.x中,它是request.required.acks。Kafka通過複製提供容錯功能,因此單個節點的故障或分割槽leader的更改不會影響可用性。如果將生產者配置為沒有ack(也稱為“fire and forget”),則訊息可能會無聲地丟失。

8、配置生產者重試次數。預設值為3,通常太低。正確的值取決於需求,對於無法容忍資料丟失的應用程式,請考慮Integer.MAX_VALUE(實際上是無窮大),這可以防止leader分割槽的brocker無法立即響應生產請求。

9、對於高吞吐量生產者,調整緩衝區大小,特別是buffer.memory和batch.size(以位元組為單位)。由於batch.size是按分割槽設定的,因此生產者效能和記憶體使用量可與topic中的分割槽數相關聯。這裡的值取決於幾個因素:生產者資料速率(訊息的大小和數量),生成的分割槽數以及可用的記憶體量。請記住,較大的緩衝區並不總是好的,如果生產者由於某種原因而停頓(例如,一個領導者通過確認響應較慢),在堆上快取更多資料可能會導致更多垃圾收集。

10、制定應用程式跟蹤指標,例如生成的訊息數,平均生成的訊息大小和消耗的訊息數。

第四部分:brocker最佳實踐!

11、Topic需要brocker的記憶體和CPU資源,日誌壓縮需要brocker上的堆(記憶體)和CPU週期才能成功完成,並且失敗的日誌壓縮會使brocker處於無限增長的分割槽風險中。你可以在brocker上使用tunelog.cleaner.dedupe.buffer.size和log.cleaner.threads,但請記住,這些值會影響brocker上的堆使用情況。如果brocker丟擲OutOfMemoryError異常,它將關閉並可能丟失資料。緩衝區大小和執行緒數將取決於要清理的主題分割槽數量以及這些分割槽中訊息的資料速率和金鑰大小。從Kafka 0.10.2.1版本開始,監視日誌清理程式日誌檔案以查詢ERROR條目是檢測日誌清理程式執行緒問題的最可靠方法。

12、監控brocker的網路吞吐量。確保使用傳送(TX)和接收(RX),磁碟I/O,磁碟空間和CPU使用率來執行此操作。容量規劃是維護叢集效能的關鍵部分。

13、在叢集中的brocker之間分配分割槽leader,其需要大量的網路I/O資源。例如,當使用複製因子3執行時,leader必須接收分割槽資料,並同步傳遞給所有副本,再傳輸給想要使用該資料的消費者。因此,在這個例子中,作為領導者,在使用網路I/O方面至少是follower的四倍,leader必須從磁碟讀取,follower只需要寫。

14、不要忽略監視brocker的同步副本(ISR)縮減,重複不足的分割槽和不受歡迎的lesder。這些是叢集中潛在問題的跡象。例如,單個分割槽的頻繁ISR收縮可能表明該分割槽的資料速率超過了leader為消費者和副本執行緒提供服務的能力。

15、根據需要修改Apache Log4j屬性。Kafka代理日誌記錄可能會佔用過多磁碟空間。但是,不要完全放棄日誌記錄,brocker日誌可能是在事件發生後重建事件序列的最佳方式,有時也是唯一方式。

16、禁用topic自動建立有關的明確策略,定期清理未使用的topic。例如,如果x天沒有看到任何訊息,請考慮topic失效並將其從叢集中刪除,這樣可以避免在叢集中建立必須管理的其他後設資料。

17、對於持續的高吞吐量代理,請提供足夠的記憶體以避免從磁碟系統讀取,應儘可能直接從作業系統的檔案系統快取中提供分割槽資料。但是,這意味著必須確保消費者能夠跟上,滯後的消費者將迫使brocker從磁碟讀取。

18、對於具有高吞吐量服務級別目標(SLO)的大型叢集,請考慮將topic隔離到brocker子集。如何確定要隔離的topic取決於業務需求,例如,如果有多個使用相同叢集的聯機事務處理(OLTP)系統,則將每個系統的topic隔離到brocker的不同子集以幫助限制事件的潛在爆炸半徑。

19、使用較新topic訊息格式的舊客戶端(反之亦然)會在brocker客戶端轉換格式時對brocker程式施加額外負擔,儘可能避免這種情況。

20、不要認為在本地桌上型電腦上測試brocker代表在實際生產環境中的效能。使用複製因子1對分割槽的環回介面進行測試是與大多數生產環境完全不同的拓撲。通過環回可以忽略網路延遲,並且在不涉及複製時,接收leader確認所需的時間可能會有很大差異。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31077337/viewspace-2212698/,如需轉載,請註明出處,否則將追究法律責任。

相關文章