Kafka Streams 2.5提供更高的高可用性和互動式查詢 - confluent

banq發表於2020-06-09

是什麼阻止您將Kafka Streams用作構建應用程式的資料層?畢竟,它具有快速的嵌入式RocksDB儲存,可為您處理冗餘,具有高度可伸縮性並提供正好一次精確的語義。
推薦博文:Apache Kafka可以替換資料庫嗎?– 2020年的更新,Kai Waehner在文中解釋瞭如何使用Kafka Streams構建高度可擴充套件的微服務,本文重點介紹了Kafka Streams到現在為止缺少的一件事:高可用性保證。

分散式系統中的基本挑戰之一是在一致性和可用性之間實現微妙的平衡。

一致性與可用性
每個應用程式都要求不同的一致性保證。從一個客戶向另一個客戶轉移資金的財務應用程式必須保持高度一致。相反,如果推薦引擎是以追求高可用性為目標,則會對一致性模型較弱的內容感到可以忍受。
Kafka和Kafka Streams都提供了許多配置來調整應用程式以達到可用性和一致性的平衡。例如,在Kafka中,調整副本,同步副本和確認的數量可為您提供更大範圍的可用性和一致性保證。

同樣,為了進行查詢,對Kafka Streams(直到2.4版)進行了調整,以實現高度一致性。系統中可以有N個副本,但是查詢支援僅限於活動分割槽。這意味著,如果您使用REST API來提供儲存在Kafka Streams中的狀態,如果其中一個處理活動分割槽的VM變得不可用,您將有停機時間。發生故障的活動分割槽僅在透過新的重新平衡重新分配它們時才能夠提供查詢,並且在發生故障之前將其還原到以前的狀態。重選和恢復的過程可能需要幾秒鐘到幾分鐘的時間。對於某些對時間敏感的應用程式,這可能是災難性的,因為無法為駐留在發生故障的分割槽上的客戶提供資料。在沃爾瑪,系統不可用構成了巨大的挑戰,

我們的挑戰:沃爾瑪規模的可用性

在沃爾瑪,我們已經使用Kafka Streams兩年來構建我們的一站式客戶資料平臺。該平臺每天吸收數十億個互動和事務事件,使用REST API提供派生的知識,並觸發訂閱特定事件的各種基於客戶的機器學習模型。電子商務中的主要用例之一是欺詐檢測。
欺詐檢測模型是交易流程的一部分,並在每次購物車結帳時觸發。因此,向模型提供資料並執行實際模型以識別欺詐的過程必須在幾毫秒內完成。用於從平臺獲取使用者歷史記錄的查詢帶有非常嚴格的SLA,因此我們必須最佳化Kafka流以實現高可用性和低延遲。我們向Kafka Streams新增了一些Kafka改進建議(KIP),從而減少了服務停機時間並幫助我們實現了單位數的服務等待時間。這些改進將在以下各節中介紹。
在雲環境中,VM變得不可訪問是很常見的,這會導致服務中斷。最大的原因之一是雲補丁。儘管修補程式對於修復錯誤和漏洞至關重要,但它們可能會影響系統可用性。單個VM上的補丁程式至少會在應用程式中觸發兩次重新平衡,一次是在離開叢集時,另一次是在補丁程式後重新加入時,這兩種操作均會導致API請求失敗。對於Walmart,每個VM的補丁大約需要10-15分鐘。虛擬機器重新加入群集後,將其從群集中刪除,在其他位置建立新的備用資料庫並選擇活動資料庫的完整工作就變得徒勞了。
為避免這種情況,一種選擇是將session.timeout.ms設定增加到15分鐘。該選項的問題是對VM上的活動分割槽的REST呼叫失敗,該故障已中斷。重新平衡過程中可用性的降低導致我們挑戰現狀,並找到一種方法來在重新平衡過程中或VM發生故障時提高應用程式的可用性。

Kafka 2.5版本中引入了KIP-535,允許狀態儲存在重新平衡期間提供舊的資料讀取,解決了上述挑戰。它能夠從備用伺服器提供查詢服務以及熱還原活動伺服器以在重新平衡期間啟用查詢的功能。
除了提高可用性之外,從備用伺服器啟用服務還提供了負載平衡的好處。如果您的應用程式收到對特定分割槽的異常高的呼叫,則備用任務可以透過為查詢提供服務來減輕負載,而使用此KIP可以實現這一任務。
KIP-535公開的分割槽資訊可用於從其特定分割槽中獲取金鑰的資料。不幸的是,儲存的內部實現會在例項上所有分割槽的所有可用儲存上進行迭代,效率低下,並且在每次查詢過程中會增加可觀的延遲。為了改進此流程,我們新增了另一項改進KIP-562

使用KIP-562從特定分割槽提供服務
允許應用程式開發人員以可以查詢特定分割槽或選擇是否查詢舊狀態的方式編寫API。以下程式碼顯示了使用此新KIP的程式碼段:

//找到活動的備用主機列表和分割槽
final KeyQueryMetadata keyQueryMetadata = kafkaStreams.queryMetadataForKey(TABLE_NAME, key, (topic, “key”, value, numPartitions) -> 0);

////使用以上資訊將查詢重定向到包含鍵“ key”的分割槽的主機

//key belongs to this partition
final int keyPartition = keyQueryMetadata.getPartition();

//獲取key所屬的特定分割槽“ keyPartition”的儲存,並檢視陳舊的儲存
final ReadOnlyKeyValueStore<String,String> store = kafkaStreams
           .store(StoreQueryParameters.fromNameAndType(TABLE_NAME,    queryableStoreType).enableStaleStores().withPartition(keyPartition));                     
String value = store.get(“key”);



使用KAFKA-9169修復備用資料庫的不必要恢復
想象一下,您的應用程式進行了重新平衡,並且在重新平衡之後,所有待機任務將使用對他們可用的第一個偏移量進行恢復,即使它們已經恢復了資料並且很熱。此過程會大大增加群集中的CPU使用率,網路和磁碟I / O,並會影響不必要的情況。對於Walmart,每個備用VM的網路I / O通常小於10 MB / s,但是由於存在錯誤,它增加到200 MB / s以上,直到完全還原了備用資料庫為止。
這是KAFKA-9169在2.5版中修復的關鍵錯誤之一。由於我們已經啟用了備用資料庫的服務功能,因此這是有害的,因為由於這種不必要的還原,備用資料庫無法服務。如果您為變更日誌主題啟用了保留時間,則偏移量可能不可用,從而導致OffsetOutOfRangeExceptions,並且儲存將被刪除並重新建立。此錯誤修復程式還透過停止備用任務中的不必要還原來幫助提高Kafka Streams群集的可用性。

 總結

ksqlDB(Kafka Streams上的SQL抽象)的流行證明了基於事件流資料庫的用例數量不斷增長。即使經過考驗,Kafka Streams和ksqlDB的未來也取決於能否透過提供高可用性和低延遲提供資料來挑戰傳統資料庫的能力。透過使用不同的事件流引擎和資料庫來構建單個應用程式,這還將減少開發人員的開銷。上面討論的所有改進旨在使我們進一步朝這一最終目標邁進。
對查詢在Kafka Streams中的工作方式感興趣嗎?互動式查詢是使用Kafka Streams應用程式提供資料的絕佳起點。要了解ksqlDB如何使用此功能,請檢視部落格文章:ksqlDB中的高可用性,容錯請求查詢
​​​​​​​

 

相關文章