流數據庫的四個關鍵設計原則和保證
實時數據處理是運行現代技術型企業的一個基礎方面。客戶比以往任何時候都希望有更快的結果,只要有一點機會,他們就會叛變。因此,現在的組織都在不斷追尋從他們的反應中減去幾毫秒的時間。
實時處理正在接管早期使用批處理的大部分方面。實時處理需要在傳入的數據流上執行業務邏輯。這與傳統的將數據存儲在數據庫中然後執行分析查詢的方式形成鮮明對比。這類應用無法承受先將數據加載到傳統數據庫然後再執行查詢所涉及的延遲。這就爲流式數據庫提供了舞臺。流式數據庫是能夠接收高速數據並在移動中處理它們的數據存儲,而不需要傳統數據庫的參與。它們不是傳統數據庫的替代品,但擅長處理高速數據。本文將介紹流數據庫的 4 個關鍵設計原則和保證。
瞭解流式數據庫
流數據庫是能夠實時收集和處理傳入的一系列數據點(即,數據流)的數據庫。傳統的數據庫存儲數據,並期望用戶執行查詢以獲取基於最新數據的結果。在現代社會,實時處理是一個關鍵標準,等待查詢不是一個選項。相反,查詢必須連續運行,並始終返回最新的數據。流數據庫爲此提供了便利。
在流式數據庫的情況下,查詢不是被執行,而是被註冊,因爲執行永遠不會被完成。它們運行的時間是無限的,對新進來的數據做出反應。應用程序還可以回溯查詢,以瞭解數據隨時間變化的情況。
與傳統的數據庫相比,流式數據庫在編寫時做了所有的工作。實現這一點伴隨着很多挑戰。首先,人們期望從傳統數據庫中獲得最低限度的耐久性和正確性。當數據總是在運動時,保持這種耐久性和正確性需要複雜的設計。然後,還有一個挑戰是如何使用戶能夠查詢運動中的數據。長期以來,SQL 一直是滿足所有查詢要求的標準。很自然,流式數據庫也支持 SQL,但是當數據一直在移動時,實現像窗口化、聚合等結構是很複雜的。
持久性查詢是一種對移動數據進行操作的查詢。它們無限期地運行,並不斷地輸出行數。持久性查詢在更新邏輯方面帶來了獨特的挑戰。關鍵問題是關於用改進後的查詢替換時的行爲 -- 它是對所有在此之前到達的數據進行操作還是隻對下一組數據進行操作?第一種操作模式的名稱是回填,後者是完全一次性處理。爲了實現完全一次性處理,執行引擎必須有一個本地存儲。有時,查詢可以反饋給其他數據流。這樣的操作被稱爲級聯模式。
既然這些概念已經很清楚了,讓我們花些時間來了解一下流式數據庫的架構細節。流式數據庫通常建立在一個基於生產者 - 消費者範式的流處理系統之上。生產者是一個創建事件的實體。消費者消費這些事件並對其進行處理。事件通常被分組爲主題的邏輯分區,以方便業務邏輯的實現。
在它們之間有一個經紀人,他確保生產者和消費者所需的流和格式轉換的可靠性。代理人通常分佈在一個分佈式平臺上,以確保高可用性和穩健性。一個流查詢引擎位於處理平臺的頂部。一個將 SQL 查詢轉換爲流處理邏輯的 SQL 抽象層也是存在的。將所有的東西拼接起來,架構看起來如下。
現在我們已經理解了流式數據庫和持久性查詢的概念,讓我們花些時間來了解它們的典型用例。
物聯網平臺
物聯網平臺要處理來自世界各地設備的大量事件。他們需要根據實時處理催生警報,並在反應時間方面有嚴格的服務水平協議。物聯網平臺還需要永遠存儲所有收到的事件,並需要對流媒體數據進行基於窗口的聚合分析。流式數據庫和持久性查詢在這裏很適合。
事件源
事件源是一種範式,應用邏輯是根據一段時間內發生的事件而不是實體的最終狀態來執行的。這有助於提高應用程序的耐用性和可靠性,因爲應用程序的狀態可以通過對事件的回覆隨時重新創建。在審計跟蹤是一個強制性要求的情況下,這很有用。
點擊流分析
點擊流分析平臺處理作爲應用程序使用的一部分產生的點擊事件。來自點擊事件的數據有時會被直接輸入機器學習模型,爲客戶提供建議和意見。持續的事件和對點擊流的實時處理是經營電子商務等業務的一個重要部分。
交易系統
交易系統每秒處理數以百萬計的交易請求,並將其與需求和供應方程相匹配以結算交易。在這種情況下,審計跟蹤是一項強制性要求,即使是最輕微的延遲也會給相關各方帶來巨大的金錢損失。
欺詐檢測系統
欺詐檢測系統需要在檢測到與典型的欺詐開始密切相關的情景時立即採取行動。他們還必須保留觸發警報的記錄和事件發生後的後續事件。考慮一個金融系統的欺詐檢測系統,根據合法所有者的消費模式檢測欺詐。它需要將事件的特徵實時反饋給欺詐檢測模型,並在標記出可能的違規行爲時立即採取行動。實時數據庫是實現此類用例的優秀解決方案。
IT 系統監控
集中監控有助於組織保持其 IT 系統始終運行 流數據庫通常用於收集系統的日誌,並在滿足特定條件時產生警報。通過事件存儲產生的實時警報和審計跟蹤是可觀察系統實施的關鍵因素。
流媒體數據庫市場並不擁擠,只有少數幾個數據庫是經過戰鬥考驗的,可以處理生產工作負載。Kafka、Materialize、Memgraph 等是其中幾個穩定的數據庫。選擇一個適合用例的數據庫需要對其功能進行詳細的比較和用例剖析。
現在讓我們把重點轉移到學習流式數據庫背後的關鍵數據庫設計原則和保證。
4 關鍵的流數據庫設計原則和保證
一個數據庫系統的完整性通常以數據庫是否符合 ACID 標準來表示。ACID 抱怨構成了良好的數據庫設計原則的基礎。ACID 兼容是指原子性、一致性、隔離性和持久性。完整性指的是保證邏輯操作中的一組語句在其中一個語句出現錯誤時能夠優雅地失敗。這樣的一組語句被稱爲事務。在早期的流式數據庫中,經常缺少對事務的支持,因此也缺少原子性。但是較新的版本確實支持事務。
一致性是指遵守數據庫執行的規則,如唯一鍵約束、外鍵約束等。如果結果的狀態不符合這些規則,一個一致的數據庫將恢復交易。隔離是單獨執行事務的概念,這樣一個事務不會影響另一個。這使得事務的平行執行成爲可能。像 KSQLDB 這樣的數據庫支持強一致性和查詢的平行執行。持久性是指從故障點恢復。架構的分佈式性質確保了現代流式數據庫的強大耐久性。
在流式數據庫的情況下,保證是指對處理事件的保證。由於數據是不斷移動的,很難保證事件的處理順序或避免重複處理。確保所有的數據被準確地處理一次是一個昂貴的操作,需要狀態存儲和確認。同樣,在分佈式應用的情況下,確保消息按照收到的相同順序被處理,需要複雜的架構。
現在讓我們來看看核心設計原則以及它們是如何在流式數據庫中完成的。
自動恢復
自動恢復是流數據庫中最關鍵的數據庫設計原則之一。流數據庫被用於高度監管的領域,如醫療、金融系統等。在這樣的領域中,故障是沒有藉口的,事故可能導致巨大的金錢損失,甚至是生命損失。想象一下,一個流式數據庫被整合爲醫療保健物聯網平臺的一部分。傳感器監測病人的生命參數,並將其發送到託管在雲端的流數據庫。這樣的系統永遠不會癱瘓,根據閾值產生警報的查詢應該無限期地運行。
由於故障不是流式數據庫的選項,它們通常是基於分佈式架構來實現的。基於節點集羣設計的流式數據庫提供了很好的容錯性,因爲即使有幾個節點發生故障,系統的其他部分仍然可以接受查詢。這種容錯性必須在開發週期的早期就被納入流數據庫的設計中。現在讓我們看看流式數據庫的自動恢復所涉及的關鍵活動。
分佈式流媒體數據庫的自動恢復涉及以下活動。
-
故障檢測
-
再平衡和智能路由
-
最終恢復
故障檢測是自動恢復的第一步。系統必須有足夠的自我意識來檢測故障情況,這樣它才能採取必要的恢復措施。在分佈式系統中,故障檢測通常是通過心跳機制完成的。心跳是一個週期性的輕量級信息,節點每一次都會向集羣的主站發送。這讓其他人知道它還活着。如果沒有收到一個節點的心跳信息,系統就會認爲它已經死亡,並啓動恢復程序。心跳信息的大小、其中捆綁的信息以及心跳信息的頻率對於優化資源非常重要。非常頻繁的心跳將有助於更早地發現故障,但它也會佔用處理時間併產生開銷。
當分佈式系統中的一個節點發生故障時,該節點所擁有的資源必須重新平衡到其他節點。分佈式系統使用受控的複製來確保數據不會丟失,即使有幾個節點宕機。一旦一個節點癱瘓,系統就會確保數據在其他節點上得到重新平衡,並儘可能地保持複製策略,以減少數據丟失的風險。
爲了維持一個高可用的流媒體數據庫,在部分故障期間進行再平衡是不夠的。因爲在流式數據庫的情況下,查詢總是在運行,系統需要確保它們持續運行。這就是智能路由的作用。智能路由有助於確保查詢持續運行並返回結果。使用故障節點上的資源的查詢被無縫地路由到其他節點。這需要精心設計,是流式數據庫的基礎要求的一部分。
最後的恢復涉及到恢復事件中丟失的狀態存儲。狀態存儲被要求確保系統完全滿足用戶配置的約束條件一次,最多一次,或者至少是處理保證。分佈式數據庫通常使用一個無限的日誌作爲真理的來源。他們還使用單獨的主題,在那裏保留時間偏移作爲恢復機制。在發生故障的情況下,這個時間偏移主題可以用來重新創建事件的時間線。
剛好一次的語義
在流式數據庫的情況下,故障情況下的自動恢復是不夠的。與傳統的數據庫設計不同,流式數據庫的設計應該確保在故障時丟失的結果不會影響下游的消費者。要完成這個任務有幾個方面。首先,系統需要確保沒有記錄錯過處理。這可以通過重新處理所有的記錄來實現,但這其中存在着風險。首先,沒有充分考慮的重新處理會導致記錄被處理一次以上。這導致不準確的結果。例如,考慮到同樣的健康護理物聯網平臺,警報是決定生命的警報。重複處理會導致重複的警報,從而造成資源的浪費。重複處理也會導致彙總的結果,如平均數、百分數計算等。
根據不同的要求,有時,事件處理中的一些錯誤可能是可以接受的。流數據庫定義了不同的消息處理保證,以支持具有不同要求的用例。有三種類型的消息保證可以使用 -- 最多一次、至少一次和正好一次。最多一次保證定義了消息不會被處理超過一次的情況,但有時可能會錯過處理。最少一次保證定義了允許重複處理的情況,但錯過記錄是不允許的。
精確一次語義保證了一個消息只被處理一次,而且結果足夠準確,以至於消費者對失敗事件視而不見。讓我們藉助一張圖來探討這個概念。
假設系統正在處理按順序來的消息。爲了表示,消息在這裏從 1 開始排序。處理器接收消息,根據邏輯對其進行轉換或聚合,並將其傳遞給消費者。在上圖中,綠色表示尚未處理的消息,紅色表示已處理的消息。每當一個消息被處理,處理器就會用偏移量更新一個狀態存儲。這是爲了在發生故障時能夠恢復。現在我們假設,處理器在處理完第二條消息後出現錯誤,並崩潰了。當處理器回來的時候,它必須從第 3 條而不是第 2 條消息重新開始處理。它應該避免對狀態存儲進行重複更新或將消息 2 的結果再次反饋給消費者。
換句話說,系統從結果的角度和系統間通信的角度都掩蓋了故障。這需要生產者、消息傳遞系統和消費者根據約定的合同進行合作。消息傳遞確認是最簡單的保證,可以幫助流式數據庫完成這個任務。契約應該能夠承受經紀人的失敗、生產者與經紀人之間的通信失敗,甚至是消費者的失敗。
處理無序的記錄
好的數據庫設計將處理失序記錄作爲一個重要方面。流媒體數據庫由於許多原因會遇到記錄丟失的情況。這些原因包括網絡延遲、生產者不可靠、時鐘不同步等。由於它們被用於高度敏感的應用,如金融和醫療,其中處理的順序是非常重要的,流數據庫必須很好地處理它們。爲了更好地理解這個問題,讓我們考慮同一個物聯網醫療平臺的例子。假設由於一時的互聯網連接故障,其中一個設備在很短的時間內無法發送數據。當它恢復時,它開始從恢復的時間開始發送數據。一段時間後,設備中的固件又發送了之前未能發送的其餘數據。這就導致了無序的記錄到達流數據庫。
爲了更好地瞭解情況,現在讓我們用一個圖來解釋這個問題。下圖有一個生產者,它發送的消息的數字從 1 開始。綠色的塊代表尚未發送的事件,紅色的代表這裏已經發送的事件。當消息。1,2 和 3 按照時間戳的順序到達,一切都很好。但是,如果其中一個消息在途中或從源頭本身被延遲,它將導致流平臺的結果被破壞。在這種情況下,消息 1 和 3 比 2 早到。流平臺在 1 和 3 之後收到 2,但它必須確保下游的消費者按實際順序收到消息。
如果不正確處理失序的記錄,處理這些記錄的流數據庫將向下遊系統提供不準確的結果。例如,讓我們說,消息表示一個溫度值,有一個持久性的查詢,找到過去一分鐘的平均溫度。一個延遲的溫度值會導致一個錯誤的平均值。流數據庫用兩種方法處理這些情況。第一種方法涉及一個配置參數,該參數定義了處理器在每個微批開始之前等待失序記錄到達的時間。微批是一組記錄,是實時查詢的一部分。微批的概念是持久性查詢的基礎。
解決失序記錄的第二種方法是允許處理器更新已經計算的結果。這需要與消費者達成一個協議。這個概念與交易的概念直接衝突,因此在實現時需要仔細設計。這隻在下游消費者能夠產生相同輸出的情況下起作用,即使它以不同的順序收到輸入。例如,如果下游消費者的輸出是一個允許修訂的表,那麼流式數據庫就可以使用這種策略。
一致的查詢結果
實現流式數據庫通常是基於分佈式架構的。傳統的數據庫設計原則認爲原子性和一致性是良好數據庫設計的關鍵支柱。但是在流式數據庫中,由於其分佈式的性質,要完成寫入的一致性是很困難的。考慮一個使用複製分區概念的流數據庫,並部署在一個節點集羣上。收入流將根據存儲模式進入不同的分區或節點。爲了確保真實的寫入一致性,人們需要確保只有當所有分區都反映它是成功的時候,流才被確認。當有多個消息作爲邏輯事務的一部分時,這是很困難的。在將交易標記爲成功之前,分別跟蹤和確認每條信息是非常重要的。
確保寫的一致性的困難也會滲透到讀的一致性。只有在讀取一致的情況下,纔有可能返回一致的查詢結果。考慮一個作爲多個持久性查詢的數據源的流,該查詢根據不同的業務邏輯對流進行聚合。一個流式數據庫必須確保這兩個查詢都作用於一個單一的真理源,並且查詢的結果反映出不衝突的值。這是一個非常困難的命題,因爲爲了處理失序的記錄,大多數數據庫以連續的更新模式運行,經常改變它們之前計算的結果。在串聯查詢的情況下,這種更新會在不同的時間涓涓細流地流向下游,一些衍生的查詢狀態可能反映了不同的源數據狀態。
有兩種方法可以解決查詢結果一致性的問題。第一種方法是通過確保在所有來自該流的查詢完成之前不確認寫入來解決這個問題。這對生產者來說是很昂貴的。因爲爲了滿足精確的一次處理要求,大多數流式數據庫都依賴於經紀人和生產者之間的聯繫(aknwoedlegemtns)。如果所有的寫入都是在查詢完成後才確認,那麼生產者就會被矇在鼓裏更久。這種方法就是寫時受阻的方法。
解決一致性問題的第二種方法是在查詢引擎層面進行。在這裏,查詢引擎推遲需要強一致性保證的特定查詢的結果,直到所有的寫入被確認。這比第一種方法成本低,因爲輸入流的寫入性能不受影響。這種方法不是延遲確認作爲查詢基礎的輸入流,而是在查詢層面進行操作。因此,如果一個查詢不需要強大的一致性保證,其結果將比其他依賴於相同輸入流的查詢更早發出。因此,不同的查詢根據其一致性配置在同一輸入流的不同版本上操作。這就要求流式數據庫保持所有計算的線性化歷史,這樣它就可以很容易地總結出多個查詢所執行的數據的版本。
流數據庫必須在數據的滯後性和一致性水平之間取得平衡,以優化性能。提高一致性水平可能會導致處理速度下降,反之亦然。
總結
流數據庫是實時處理應用程序的基礎。它們不是傳統數據庫的替代品,而是幫助滿足那些需要在永不停息的數據流上始終進行處理的獨特要求。設計一個流式數據庫是一項複雜的任務,因爲在處理流式數據時涉及到一些限制。實現讀取一致性、處理過期數據、確保一次處理和自動恢復是設計流數據庫時考慮的典型設計原則。
來源:
https://www.toutiao.com/article/7167792751663284772/?log_from=b30ddbd4e6ff4_1668996967149
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/fd9Ydu6qSZKr1BHlE0gC3w