聊一聊實時計算系統設計

本文做者:AIOps智能運維算法

做者簡介數據庫

餓馬搖鈴    百度雲高級研發工程師後端

 

負責百度雲智能運維產品(Noah)數據採集和計算方向架構設計和研發工做,對分佈式系統架構有必定實踐經驗。網絡

 

乾貨概覽架構

本文是我在實時數據計算系統的設計、開發、運維生涯的一部分經驗總結。主要介紹一些設計思路和常見問題的解決方案,不關注具體計算框架的使用。併發

本人主要致力於監控系統數據計算方向,主要業務場景有:監控數據的ETL、數據匯聚、分析、異常檢測等。因爲監控系統對時效性有較高需求,因此咱們的計算系統更偏向實時系統,根據業務場景的不一樣,延遲從數百毫秒到分鐘不等。下文提到的計算架構更可能是指整個計算處理通路,主要以監控場景下的系統設計爲例,相信與其餘場景下的架構也有相通之處。負載均衡

文章從如下幾個方面展開。框架

首先,在第1節,咱們簡述不一樣數據規模和場景下,監控系統計算架構的可選方案。在公司、業務發展的不一樣階段,主要矛盾不一樣,可以投入人力物力資源不一樣,須要選擇合適的架構方案。less

實時計算系統的設計有一個核心問題:如何同時知足高時效性和數據準確性?在現實環境中,高時效性和準確性很難同時達到,第2節中介紹了Watermark機制以實現二者的平衡。運維

第3節介紹百度監控系統的實時計算系統架構,描述了其基本組成、思路和實現中一些常見問題的解決方案。

最後,簡單討論了實時計算系統可用性建設

監控系統計算架構選型

對於包含數百到千級別節點的小集羣,數據規模有限,全部採集、存儲、計算邏輯均可以集成在一個模塊中實現,這種多爲領域專用系統。監控系統中,典型的有Prometheus,其採用單服務節點架構,提供簡單的HA模式進行容錯,這種架構的優勢是部署使用簡單。受限於單機資源,適合部署自治的多個實例,每一個實例監控不一樣服務。大規模集羣狀況下,要實現全局的監控,須要合併多個監控實例的數據,在配置分發、可用性、容錯、自動化部署管理等方面都須要更多的工做。從開發角度考慮,因爲功能耦合嚴重,不利於開發升級。

比起領域專用系統,還有一種架構是使用通用性更強的OLAP系統來實現實時或者近實時的計算功能,如TSDB、ElasticSearch等系統都有必定的聚合計算能力。這些分佈式系統都有水平擴展能力容錯能力,但難以實現複雜業務計算,同時延遲不可控,複雜查詢或大批量數據查詢的延遲可能會達到分鐘級別。

更多的狀況下咱們採用存儲計算分離的方案,以便存儲和計算的各自演進和平臺化。一般由一個提供精細查詢能力的存儲服務與一個計算模塊組成。計算模塊根據計算規則從存儲系統中拉取數據並進行計算,這個架構的瓶頸在於存儲系統可以支持的查詢規模。根據咱們的經驗,基於精心設計的內存數據庫集羣,可以承受百萬級別的併發查詢。這種架構下計算任務多爲週期性調度,當查詢性能降低時會形成任務的堆積。這個模型不方便處理延遲數據,須要必定機制預測數據完整時間,調度任務進行重算,任務調度的複雜度高。基於索引查詢的計算系統的延遲取決於計算輪詢的週期,適用於聚合類的涉及時間窗口的運算操做。

更高數據量和計算規則的狀況下,流式計算是一個天然的選擇,下降了寫存儲、索引、查詢的消耗,計算延遲大幅下降。

當數據量進一步上升,須要的網絡吞吐、計算能力驟增,後端的算力難以跟上數據量的增加。這時候能夠將計算能力分散到全鏈路,將計算提早到數據產生端。在監控系統中,經過在採集端進行預計算和ETL操做,提取或整合有用信息,對於實時日誌採集,能大幅度下降傳輸到後端的數據量。放到更大的視角上,這種將算力下放到數據源的思想,是目前大熱的邊緣計算的一個主要思路。

近年來,以AWS Lambda爲首的Serverless計算架構獲得了更多的重視。這個模型將計算抽象爲事件以及觸發的計算邏輯,計算邏輯實際由框架調度、分配資源執行。用戶只須要編寫計算邏輯,而不用關心可用性、可擴展、負載均衡等後端代碼,極大的下降了開發成本。經過按需調度,自動擴縮容,業務運維方再也不關心容量規劃等問題。私覺得當前常見計算框架的Serverless化是一個值得嘗試的方向。目前的Serverless框架還存在不少問題,例如調度初始化虛機、容器的成本高,缺少狀態存儲等,比較適用於無狀態的計算。

通常來講根據場景需求,一般對不一樣的架構會組合使用。例如百度監控系統內部是以流式計算與近線計算相結合的方式提供服務的,近線計算從時序數據庫(TSDB)中拉取數據進行計算。對於Trace、在線數據分析等具備比較複雜查詢需求可是相對比較低頻的操做,更適合基於索引查詢的架構。

準確性與時效性

對於實時系統,咱們對時效性有更嚴格的需求,可是一般高時效性伴隨着低準確度,兩者不可兼得。在分佈式環境下,自然存在長尾的延遲數據,這多是原始數據自身的延遲,也多是由採集點異常、網絡延遲、網絡抖動、數據通路中負載等形成的延遲。數據源越多,分散的越廣,這個長尾效應就會越嚴重,等待數據完整所須要的時間也越長。咱們須要在最終數據的準確性和時效性間作折中。

不一樣場景對二者的需求不一致,一般來講報警、自動止損等操做須要最高的時效性,可以容忍必定的精度缺失,在審計、訂單等數據上咱們更多的追求準確性,時效性能夠適當放寬。解決這個折衷的經常使用機制是Watermark

Watermark是在數據流中增長標誌信息,用以指示一個窗口內的數據已經「徹底」到達,能夠進行計算。

示例:假設咱們要統計10s內到達的事件數目,以事件時間(Event Time,即事件攜帶的時間,多爲事件產生時間)做爲時間基準。以下圖所示,橫線爲Wall Time時間線,單位爲s。圓球表示事件,圓球裏面的數字爲事件時間,其虛線指向產生時間,圓球正對的Wall Time時間線上的點爲被計算系統處理的時間(Process Time),兩個時間之間的差值爲實際延遲。每一個事件都或多或少存在延遲,其中數字爲45的圓球延遲最大。對於事件時間[40, 50]這個匯聚窗口,假設咱們將Watermark線畫在53處,則咱們認爲數據在53以前已經徹底到達,已經接收到的那些數據能夠參與匯聚,Watermark以後到來的事件則忽略。

具體怎麼肯定Watermark一般取決於需求,對於數據點數量級比較穩定的場景,能夠設置一個到達的數據點的比例,在某一個判斷週期內,只要到達的數據點比例知足閾值則可添加Watermark。主流開源計算框架對Watermark的實際定義不盡相同,具體使用參考對應計算框架的定義。

私覺得Watermark機制隱含的一個重要思想是將數據準確性的定義交還給用戶,讓用戶決定。產品或者架構上的功能,存在多種方案的狀況下,選擇最泛化的那個方案,暴露出參數而後讓用戶來選擇,不要本身替用戶作決定。固然爲了簡化實現成本和用戶使用成本,能夠設置固定的一些選項,並選擇一個需求最大的做爲默認值。

一般Watermark以後的過時數據點會被丟棄。常常的,除了知足高時效性需求外,咱們也須要在以後保證數據的最終準確性,即在必定時間段以後的數據是準確的。經常使用思路是部署兩套計算系統,流式計算用以實現低延遲可是準確性低的需求,批量計算用於補償計算數據的準確性,這就是Lambda架構。最典型的使用Lambda架構的場景是從日誌中統計PV/UV,一般是一個流式採集系統和流式計算框架進行實時的PV/UV計算,同時有一套離線系統,按期拉取原始日誌,經過批量計算系通通計準確的PV/UV數值。一般這種架構的缺點是兩套系統的資源消耗,開發運維成本高

當前主流計算框架如Spark和Flink對流式和批量計算進行了統一抽象。能夠必定程度下降兩套系統的開發運維成本,下降了不一樣框架的開發運維成本,兩次計算的的資源消耗依舊存在。

對於知足交換率和結合率的算子,如常見的統計方法(MAX/MIN/SUM/COUNT),在存儲側支持相同運算的狀況下,能夠將兩次運算合併成一次。咱們內部稱這個方案爲多版本,即數據生產一部分就匯聚一部分,每次匯聚產生一個數據版本,由存儲在寫入時合併,或者在查詢時合併。本質上,這是將匯聚的功能遷移了一部分至存儲。

百度監控實時計算系統架構

百度監控系統的實時計算系統承擔了監控系統數據處理棧的主要計算功能,天天處理數千億條消息。本節在實際系統的基礎上,進行了必定的抽象,介紹一個較爲通用的系統架構。

如圖所示,架構主要包含如下組件:

  • 接入模塊:包括數據拉取和數據接收,前者主動拉取數據,後者接收由上游模塊推送的數據。

  • 分發模塊:根據配置的計算規則,過濾訂閱的數據,並根據調度策略、集羣狀態將規則對應的數據分配到一個或多個處理單元進行計算。

  • 處理單元:包括一個物理計算模塊和對應的輸入輸出消息隊列。物理計算模塊執行實際的業務計算邏輯,不一樣處理單元間能夠是同構的也能夠是異構的,根據不一樣的業務場景和用戶需求,可使用不一樣的技術棧。

  • 控制模塊:接收用戶提交的計算規則和管理操做,分配調度資源,產生對其餘模塊的控制信息。

  • 數據推送模塊:拉取計算結果,根據計算規則將數據分發到下游模塊。

每一個物理計算模塊都對應一個輸入和輸出消息隊列,以將數據接入、據輸出與計算層隔離,增長一個新的第三方系統的交互不會影響計算功能。升級變動物理框架不會影響其餘組件。

因爲大數據處理框架,在其數據規模、節點數目達到必定規模時,其處理性能以及異常恢復速度都會降低。咱們將一個固定計算能力以及配套的資源(如消息隊列)抽象爲一個處理單元,每一個處理單元處理一部分的數據,取決於計算功能的物理實現,這個處理單元能夠對應一個集羣或者一個做業。一個處理單元的具體規模取決於具體的技術選型和硬件條件。確認處理單元的好處是便於容量規劃,能夠以一個處理單元做爲粒度進行擴縮容。若是須要嫌粒度過大,分層次進行擴縮容,先在一個處理單元內部擴展直到極限,以後啓動一個新的處理單元。

實現中須要考慮如下幾個點:

1 負載均衡

負載均衡發生在系統的每個層次。

數據接入層與和分發模塊之間的採用隨機發送的策略以均衡分發模塊的壓力

數據拉取和數據推送模塊須要動態平衡每一個實例上的拉取或推送任務,經常使用的策略是一致性哈希,以每一個任務的實際數據量做爲權重。

計算過程是最須要考慮負載均衡的場景,聚合計算一般會遭遇數據傾斜問題,即某些key的數據量遠大於其餘,這就形成匯聚該Key的任務OOM。下面提供幾種經常使用解決思路:

  • 對於知足交換率和結合率的計算方法,如MAX/MIN/SUM/COUNT等,能夠添加多層預聚合,下降最終聚合的數據量。預聚合層次間能夠隨機方式,最終匯聚以前按Key哈希。

 

  • 負載均衡或者說任務調度對應Bin Packing等一系列等價的最優化問題。這些問題是NP-Hard的,能夠經過近似算法來逼近,典型的有First Fit算法。實現時通常須要自定義計算框架的分區邏輯,如Spark能夠經過自定義Partitioner來實現。

2 控制節點扇入扇出規模

不管是具有狀態副本的分佈式存儲系統、基於DAG的分佈式計算系統仍是Stateless的接入集羣,當集羣規模持續增大時,節點間交互會顯著增大,最差的狀況下全鏈接,擴容節點會有指數級的鏈接增加。這會嚴重影響系統對水平擴容能力,擴容帶來的收益跟不上單機資源消耗的增加。

對於分佈式系統,經過控制集羣或者做業規模能夠實現必定程度的控制,對於接入模塊,能夠限制下游鏈接到上限。

可用性

對於可用性要求高的服務能夠多集羣熱備的方式,在上述架構中,能夠經過運行多個並行的處理單元處理相同的數據流來實現。也能夠部署整個集羣,經過採集端多寫的方式複製數據流。最後須要根據輸出結果的延遲、準確度等判斷策略選擇一個計算結果輸出。

服務無損升級,能夠經過啓動一個新的計算單元,並行處理數據,待數據「預熱」後,進行切換。

在部署時,接入模塊儘量的靠近數據源,保證每一個地域一套。系統多地域部署,每一個地域內部模塊間儘可能自治。接入端發送數據時優先發送本地域,異常時嘗試其餘地域。模塊間交互能夠打QoS(服務質量)標籤增長網絡優先級以下降網絡丟包。

監控上,除了基礎資源、流量等監控外,最重要的是全通路時延監控,常見方案是構造業務流量,統計在系統中的延遲。這個延遲指標一般是多維度的,根據部署和業務使用狀況可能須要關注不一樣地域,不一樣業務,不一樣處理通路的延遲。這些延遲指標,能夠指示系統進行流量調度或者資源的重分配。

總  結

本文簡單介紹了百度的分佈式監控計算系統架構的演進和當前的實時計算架構,並提供了部分常見問題點解決思路。架構是不斷在演進的,咱們的系統僅僅是「夠用」,還有更多的工做須要開展,如架構的輕量化,統一易用的計算表示層,計算的自動優化等。

因爲我的水平有限,若是行文中有錯誤,或者有須要進一步探討的,請在留言中指出。

原文連接地址:https://developer.baidu.com/topic/show/290317

相關文章
相關標籤/搜索