更多深度文章,請關注雲計算頻道:https://yq.aliyun.com/cloudlinux
阿里雲數據事業部強琦爲你們帶來題爲「流式計算的系統設計與實現」的演講,本文主要從增量計算和流式計算開始談起,而後講解了與批量計算的區別,重點對典型系統技術概要進行了分析,包括Storm、Kinesis、MillWheel,接着介紹了核心技術、消息機制以及StreamSQL等,一塊兒來了解下吧。算法
增量計算和流式計算sql
流式計算
流計算對於時效性要求比較嚴格,實時計算就是對計算的時效性要求比較強。流計算是利用分佈式的思想和方法,對海量「流」式數據進行實時處理的系統,它源自對海量數據「時效」價值上的挖掘訴求。數據庫
那麼,一般說的實時系統或者實時計算,嚴格意義上來講分紅三大類:編程
ad-hoc computing(數據的實時計算):計算不可枚舉,計算在query時發生。windows
stream computing(實時數據的計算):計算可枚舉,計算在數據發生變化時發生。安全
continuous computing(實時數據的實時計算):大數據集的在線複雜實時計算。服務器
增量計算
增量計算是分批,也就是batch,每一個batch會計算出一個function的delta值,數據的一個delta最終會變成對function的一個delta值,最終經過增量計算達到效果。網絡
batch => delta: f(x + delta) = g( f(x), delta )架構
其實是在數據的delta值上計算的一個結果,這個f(x)咱們稱之爲oldValue,整個function的一個oldValue從公式就能夠看到,整個增量計算與全量計算和批量計算有很大的不同的地方,就在於它是有狀態的計算,而批量計算系統和全量計算系統是無狀態的計算,因此這就會致使整個系統的設計思路理念和整個的容錯機制會有很大的不一樣,相對於oldValue本批次的數據,delta做爲一個輸入,總體上是一個有狀態的計算,它會在系統的時效性、系統的複雜性和系統性能之間去作tradeoff,若是batch裏的數據量是很是少的,那這個系統表現出來的時效性是最實時的,固然,整個系統的容錯吞吐就會受到影響,就是說一批次的數據量是比較少的狀況下,整個的系統吞吐會比較低,整個系統的容錯複雜度也會比較高,那麼在增量計算狀況下,它有哪些優點呢?
1.相比之前的全量計算,中間的計算結果是實時產出的,也就是說它的時效性是很強的;
2.咱們把一個計算平攤在每個時間段,能夠作到平攤計算。整個集羣的規模是受峯值的影響,雙十一的峯值流量是很是大的,若是按照最峯值的流量去計算,整個服務器資源是相對較高的,若是可以把傳統的計算平攤在每一分鐘每一秒,實際能夠起到下降成本的做用;
3.整個數據處理鏈路若是放在一次Query中進行處理,也便是所有的數據在進行一個function的計算時,會大量膨脹中間結果,也就是說像Group By Count會到達200G,而增量計算能夠作到中間結果不膨脹;
4.增量計算是一個有狀態的計算,在分佈式領域,有狀態的failover策略會跟無狀態的計算系統大相徑庭,可是它的優點是恢復快,任務能夠切成不少碎片去運行,一旦任務由於任何幾臺服務器的抖動而宕機,整個的恢復是從前一次有效的batch開始計算,而不是像全量計算和離線計算同樣,所有要從新進行計算,當在離線計算和在線計算混合部署的狀況下,這顯得尤其重要;
5.增量計算把一大塊數據分批去計算,所以在批量計算裏面常常遇到會一些數據傾斜問題在增量計算並不會遇到。在真實場景下,數據傾斜會對整個計算系統產生很是致命的影響,因此假設不一樣的節點之間數據傾斜比是1000,這個實際是很日常的,雙十一的時候,光小米一家店鋪就作到了很高的銷售額,小米店鋪和其餘店鋪的成交是上萬倍甚至幾十萬倍的scale,傳統的分佈式計算的整個計算延時是受最慢的那個節點影響,若是把所有的數據分批次,實際上對於每一批來講,數據的傾斜度就會緩解,並且每一個批次是能夠並行去運行的,因此這能夠大大地去下降整個計算任務在數據傾斜狀況下的運行效率問題。
增量計算和流式計算應用場景
日誌採集和在線分析:如基於訪問日誌、交易數據的BI算法分析。比較有名的像Google的統計、百度的統計,一些網站根據訪問日誌,會分析出各類的UV、 PV、 IPV等運營指標,有了流式計算,就能夠對這些訪問的時效性作到秒級、分鐘級的監控,好比雙十一當天,不一樣的店鋪會經過店鋪的實時訪問狀況來決定後面的運營策略;
大數據的預處理:數據清洗、字段補全等;
風險監測與告警:如交易業務的虛假交易實時監測與分析;
網站與移動應用分析統計:如雙11運營、淘寶量子統計、CNZZ、友盟等各種統計業務;
網絡安全監測:如CDN的惡意攻擊分析與檢測;
在線服務計量與計費管理系統 搜索引擎的關鍵詞點擊計費;
此外,流式計算和增量計算也應用在工業4.0和物聯網上。
流式計算的數據特色
流(stream)是由業務產生的有向無界的數據流。
不可控性:你不知道數據的到達時機以及相關數據的順序,對於數據質量和規模也是不可控的;
時效性要求:在容錯方案、體系架構和結構輸出方面都與傳統的計算是大相徑庭的;
體系缺失:傳統學術領域已經對批量計算和離線計算的體系研究的很是成熟,而在實時領域如數據倉庫中間層等領域都是缺失的,包括數據源管理、數據質量管理等等。
另外,數據處理粒度最小,能夠小到幾條數據,對架構產生決定性影響;
處理算子對全局狀態影響不一樣,有狀態、無狀態、順序不一樣等;
輸出要求,好比一致性和連貫性等。
整個流計算會對系統有很是多的不同的要求,這就會致使整個系統有很是大的複雜性,跟離線很是的不一樣,咱們的計算仍然要求時效性、要求快,質量上要求它的計算必定是精準的,對容錯的要求,不論你的機器、集羣、網絡硬件有任何的宕機,計算應該是持續穩定,對整個計算的要求也是很是多樣性的。關於多樣性,不一樣的業務場景,對計算的結果要求也是不同的,有些要求精確,一點數據都不能丟、精度損失,還有的業務場景要求能夠多可是不能少,還有丟數據有一個sla在保證等,因此種種特色致使咱們作流式計算和增量計算系統會面臨與傳統的離線計算和增量計算徹底不一樣的要求。
與批量計算的區別
從架構角度,增量計算、流式計算和離線處理、批處理有什麼本質的區別?
與批量計算的區別如上圖所示,好比全量計算設計理念是面向吞吐,而流式計算是實時計算的一部分,面向延時;隨之而來的整個全量DAG是一個串型的DAG,是一個StageByStage的DAG,而流式計算的DAG是一個並行DAG,也就是說Batch跟Batch之間是徹底能夠並行的,離線的批量系統它的串型化和Streaming場景下的並行化,它們在整個數據的時效性上
有很是大的區別,特別是在Latency的體現。
典型系統計算概要分析
下面將向你們介紹業界比較經典的幾個流計算產品:
Twitter Storm
Storm是Twitter內部使用開源被普遍使用的一套流計算系統,那麼它的一個核心概念是說,一個任務要建立一個Topology,它表示了一個完整的流計算做業,它的最開始的源頭名字叫作Spout,作收集數據的任務,它的前面能夠掛任何的數據源、任何一個隊列系統甚至能夠對接文件,那麼Bolt是它的具體計算任務所在的載體,而Bolt裏有諸多的Task,它是在Spout和Bolt裏負責具體一個數據分片的實體,它也是Storm裏調度的最小單位。Acker負責跟蹤消息是否被處理的節點。Storm的整個容錯是採用源頭重發的消息機制
源頭重發在網絡流量激增的狀況下,會形成系統的雪崩風險大大提高。上圖是兩個Storm的做業,它先從源頭讀出數據,而後進行filter過濾,最終進行join,join後進行一些邏輯處理。
Nimbus–Zookeeper–Supervisor
Storm採用了Nimbus Supervisor之間的方式進行任務調度和跟蹤,它們之間是利用Zookeeper來進行通信,Nimbus至關於一個全局的任務Master,負責接收Topology,而後進行二重的資源調度,而且將調度的信息記錄到Zookeeper中,按期檢查Zookeeper中的各類Supervisor的心跳信息,根據心跳狀態決定任務是否進行從新調度,而Supervsor充當着每臺物理機的一個watchdog,它在輪詢Zookeeper中的調度任務信息,而後接收到發現有啓動任務的信息,就會拉啓進程,啓動Task,同時按期要把心跳信息寫入Zookeeper,以便Supervisor來作出從新調度或者系統的重發操做。
消息跟蹤機制是Storm的核心,保證消息至少被處理一次,它追蹤源頭信息的全部子孫信息。
基本思路以下:
Acker節點是進行消息跟蹤的節點,以源頭消息的ID爲hash key,來肯定跟蹤的Acker,源頭信息對應的全部的子孫消息都有該Acker負責跟蹤,而消息樹上每產生一個新的子孫消息,則通知對應的Acker,子孫消息被處理,而後再去通知對應的Acker,當Acker裏全部的子孫消息都被處理的時候,那麼整個數據處理就完成了。
子孫的產生是由父節點,而處理是被子節點。因此Storm用了一個很是巧妙的異或方法,當父節點產生這個消息時,產生一個隨機數,把這個隨機數異或到Acker裏,Acker把這個隨機數傳遞到下一步的節點,當這個節點正確被處理之後,再把這節點發送給Acker去作異或,因此Storm利用了這個Acker機制來壓縮整個數據的跟蹤機制,最終保證任意節點出現宕機而值不會變成0。
Transactional Topology
光有以上的機制,還遠遠不夠。被系統重發的消息沒有任何附加信息,用戶沒法判斷消息是不是被重發的等一些問題還有待解決,爲解決消息被重複處理的問題,Storm 0.7.0之後版本推出了Transactional Topology進行改進,
原理以下:
在Spout上將源頭消息串行劃分紅 Batch,爲每一個Batch賦以遞增的id,記錄在Zookeeper中,利用Acker跟蹤Batch是否被徹底處理完成,超時或者節點異常,Spout重發Batch內的全部消息,不影響中間狀態的操做能夠併發的執行,例如 Batch內的聚合操做,用戶代碼利用惟一的Batch ID進行去重。
整個Topology同一時刻只能有一個Batch正在提交,以保證在每一個節點上Batch串行遞增,簡化用戶去重的邏輯。
Storm優缺點
優勢:消息在框架內不落地,處理很是高效,保證了消息至少被處理,Transactional Topology爲消息去重提供了可能,調度模式簡單,擴展能力強(關閉重發模式下),社區資源豐富,擁有各類常見消息源的Spout實現。
固然Storm也有本身的劣勢:Transactional Topology對Batch串行執行方式,性能降低嚴重;Batch太大過小都有問題,大小須要用戶根據具體業務分狀況設置等。
Amazon Kinesis
Kinesis系統是一種徹底託管的實時處理大規模數據流的開放服務。
全部節點運行於EC2中:相對Storm來講,它採用了消息節點內部重放的系統,而不是像Storm那樣子源頭重發,它的全部的節點都已經在EC2中,無需單獨的調度策略、複用安全、資源隔離機制,且擴展性好、彈性可伸縮。
只支持單級Task,能夠利用多個Stream組成複雜的DAG-Task,用戶代碼須要實現DAG-Task內部的消息去重邏輯。
數據收集與計算獨立:數據收集模塊(Shard)對消息進行持久化,最長保留24小時;能夠Get方式從其它系統中讀取Shard數據,計算模塊(Kinesis App)處理被推送的數據,Instance個數與Shard個數相同;用戶代碼能夠自主控制Checkpoint節奏。
用戶能夠自主調用相應的SplitShard\MergeShard接口,Stream上全部App的併發度隨之調整。具體實現方法以下:
每一個Shard串行將接收到的消息寫入S3文件中,SplitShard後,原有Shard再也不接收新數據,原有Shard對應的全部App的Instance處理完消息後關閉,啓動新的Shards(兩個)和對應新的Instances。
使計算能夠更加的彈性,服務的可用性也更高。
Google MillWheel
MillWheel系統是利用內部支持Snapshot功能的Bigtable來進行持續化中間結果,將每一個節點的計算輸出消息進行持久化,實現消息的「不丟不重」。
區別於Storm的是,它沒有複雜的跟蹤樹。由於每一級都把它的輸出消息進行持久化,用戶能夠經過SetTimer\ProcessTimer接口解決用戶代碼在消息到來時才能取得控制流的弊端,而後在源頭節點(Injector)上將數據打上系統時間戳,每一個內部節點(Computation)計算出全部輸入Pipe上的最小時間戳,向全部輸出Pipe上廣播當前完成的最小時間戳,用戶能夠利用Low Watermark這一機制解決消息亂序或一致性問題。
核心技術
那麼,流式計算和增量計算中最核心的一些技術和難點有哪些呢?
從這張圖能夠看到,整個流計算是由一個複雜的Topology所構成。那麼,從輸入到輸出,其中比較重要的兩個角色一是Jobmaster,一是Coordinator。Jobmaster是每一個Job負責運行時的一個master;而Coordinator是剛纔所說的消息跟蹤的一個角色,因此Coordinator最好是徹底能夠作到無狀態的線性擴展。
Batch數據從源頭進入後,進入Source節點,Source節點會從消息源讀取數據,藍色的部分表明着Worker節點,藍色節點再向橙色節點進行數據傳輸的時候,遵循着Shuffle的方法,能夠是哈希的方法,能夠是廣播的方法,也能夠是任何用戶自定義的方法,output節點會將輸出結果向在線系統輸出,或者向下一級MQ節點輸出,輸出的結果也是按照Batch去對齊。
系統邊界-數據收集/結果數據
拉:從消息隊列(Kafka)、存儲(Hbase、HDFS)等系統讀取數據,而且藉助這些源頭已經持久化的數據實現系統的故障恢復;涉及第三方服務系統受權。
推:須要實現Http處理模塊(Apache、Nginx等),更須要解決故障恢復問題。
訂閱:結果數據寫入消息隊列,業務方訂閱,進入本身在線存儲系統。
服務:直接提供在線數據服務;涉及第三方服務系統受權;結果數據時鐘對齊。
shuffle機制
數據如何在處理節點之間流轉,這就涉及到shuffle機制了。
在流計算的處置機制下,數據採用了push模式,它整個數據不落地,對於數據傳輸的時效性是比較好的;另外,消息機制是須要解決丟數據和重數據的問題,框架也須要保證消息的有序性。
計算節點
流計算的計算進程是longlive的,即使沒有數據進程也在,因此決定了咱們的系統不一樣的調度方式、不一樣的消息機制。計算的容錯採用任務跟蹤機制,最重要的一點,流計算的計算是個有狀態的計算,這個中間狀態的存儲方式、容錯關乎着整個計算的時效性、正確性、吞吐等。
分佈式挑戰和服務化訴求
離線計算系統對整個編程模型進行了約束,因此它在計算規模以及容錯上面已經有了很是成熟的研究,可是在流計算狀況下,它在擴展能力上集羣規模的上限是多少?計算做業是否能夠線性增長?
用戶針可不能夠從新定義等價的DAG來避免數據傾斜(犧牲性能),同時,如何避免傾斜帶來超時/雪崩的問題,數據動態的變化如何作到實時調整?
數據如何高可靠存儲,集羣擴容、系統代碼升級時是否須要中止服務?單節點故障是否會致使總體服務的不可用?此外,咱們不可避免地面臨着多租戶管理的問題,也就是受權鑑權 、資源隔離;還有計量計費、安全體系和運維體系怎麼保證等等。這都是作流計算系統面臨的一些核心問題。
增量計算語義
咱們提出了新的模型MRM,它分爲三個主要階段:
Local階段,是指Batch的Local操做,這個語意徹底等同於MapReduce,能夠認爲離線計算或者全量計算,是一個只有一個Batch的增量計算,因此這時候的Map語意是徹底同樣的;
Reduce階段是一個Aggregate階段,至關於在Batch內的數據作一次從新的組合,可是增量的語意告訴咱們必定要作跨Batch的數據的結果合併。
Merge階段,跨批數據作全局的聚合計算。
上圖爲一個簡單的wordcount例子,按照這樣的Batch去分,能夠看到Map階段每一個Batch的輸入、輸出,而後Reduce輸出,第一個Batch輸出7,第二個Batch輸入5,依此類推,初始化狀況下OldValue爲0,那麼,Merge很簡單,就進行0和7的合併操做。在這個case下面,進行一個count操做,就是7+0在Batch2,它把本次的Reduce結果5和上一次Merge的全局結果再進行一次Merge12,依此類推,因此你們能夠看到對角線的顏色,這就是一輪的Merge的結果會成爲下一輪的OldValue。
能夠看到,貫穿始終的是一個很重要的Batch概念,它是系統跟蹤數據/時效性處理的最小單位。其實Batch是一個能夠scale的概念,它能夠退化爲全量計算,也能夠把一條數據放在一個Batch裏,能夠作到時效性很是高。這二者系統的吞吐、時效性會有大相徑庭的表現。
增量計算具有三要素:肯定性、可加性和可逆性。
圖中case是說,假設在雙十一有兩行sql,首先按照賣家ID去Groupby,我要統計賣家的實時成交狀況,是按照sellerid爲11賣家,假設剛開始沒賣,第二行按照每10塊錢分制方圖,
依此類推,就像你們看到雙十一的阿里巴巴大屏同樣,它是實時滾動的。
sellerid爲11的這個賣家剛開始沒賣東西,第0檔如今沒賣家,第一檔當前時刻已經有10個賣家了,第七檔有53位賣家,賣家爲11作成了一個5塊錢的生意,那麼整個計算11這個0會變成5,如今屬於第一檔,那麼就把第一檔值由0變成1,可是緊接着,11號賣家又作成了16塊錢的生意,someMoney就會變成21,21屬於20到29區間,也就是這個檔位原來有10個賣家,如今變成11個賣家,可是重要的是,應該還把原來第0檔的那個1減掉,第一要把如今檔位加上去,還要把原來對其餘檔位的貢獻要撤銷掉,這就是咱們說的可逆性。
咱們須要把這樣的UDEF,不只要作一個正像操做,同時也要去實現一個負向操做。意思就是,把原來的那個值對系統狀態的影響讓用戶有機會撤銷掉,能夠看到整個增量計算的一個
增量語意的rollback,至關於對數據庫領域的物化視圖,兩個物化視圖實時更新,一個物化視圖嵌套一個物化視圖,必需要對以前的計算有一個回穩操做,這是增量計算的一個很是本質的要求。
消息機制
消息機制是整個流處理系統的核心,它會影響計算延遲、容錯機制、可擴展性、服務可用性等方面,整個消息過程從分發到接收處處理相應用戶的work代碼,咱們將這個消息框架定義爲shuffle framework,對於消息的發送和接收利用Zookeeper來記錄整個DAG。也能夠利用消息隊列好比Kafka,就像咱們每一步都落地、存儲這樣的方式來定義shuffle。
對於解決消息的丟失問題,有兩種作法:
一是消息源頭的重發。每個節點跟節點之間是用Push過去的,中間結果不會進行任何的可靠存儲,因此運行效率是比較高的,可是當一個Topology比較大的時候,任意一個節點的宕機或者超時都會引發總體的重發和重作,進而增長雪崩的風險;
一是節點內部重發。它跟前者的優點劣勢恰好反轉,它須要每一步落地,運行效率會比較低,系統也會產生大量的文件碎片,它的好處是重發重作只依賴於父親節點。
消息源頭重發機制
方案
依賴源頭可靠的數據存儲系統(Kafka、HBase等),源頭存儲系統既是消息收集模塊,又是消息重發的數據源,中間節點消息不落地,跟蹤源頭消息,超時後重發。
雪崩
分佈式系統中最多見的異常狀態是網絡的抖動。在流處理系統中,消息跟蹤代價過大,通常的跟蹤機制並不會在跟蹤結果中詳細標示出是哪個節點出現故障。這種不加區分的源頭消息重發,會使得原本正常的節點由於其它單點的故障,也要接收大量的重複數據,消耗寶貴的網絡資源,使網絡情況進一步惡化。而後這種狀況會一步一步地變大,最終形成整個集羣網絡的癱瘓。
針對以上問題,咱們進行了消息命令流的大量約減,咱們不會跟蹤具體每個Batch內的數據,而是每一批發送一個特殊的命令流來跟蹤。咱們要求每一個消息有惟一的batchid,而且與源頭節點的offset可重入,還須要這樣的Batchid去作消重,也做爲一個惟一的版本,每次重試咱們會在Batchid後面新增一個attemptid。
固然這樣的問題仍是存在大量的通信量,節點Crash後整個表如何重建等問題。
消息節點內部重放
節點接收到消息後,先落地,再計算;節點出現故障,從存儲系統中重放;按期作 Checkpoint,減小重放代價。
這種方案特色是方案簡單,但依賴於可靠、高效的存儲模塊;局部故障對全局影響小,系統可擴展性好,雪崩的風險也極大地下降。
消息去重
消息去重策略是上下游節點之間經過自增的ID協議。
發送端消息從0開始賦值惟一的id,每次加1;發送消息後等待接收端返回信息,成功或者消息重複纔可發送下一消息,不然一直重試。
接收端在內存維護一個去重表,Key是上游節點對應的ID,Value是對應上游節點最後一次接收成功的消息id;接到新消息,首先在去重表中,根據PipeID比較消息id是否自增長1;若是小於等於已有消息id,則直接返回消息重複;不然,將消息寫入存儲系統中,以後更新去重表,並返回發送端消息接收成功。
爲了不形成大量的IO浪費,咱們也會使用讀寫分離技術。
寫模塊:
節點將接收到的上游消息首先進行持久化;
將數據和存儲系統中的Offset信息經過內存(或者網絡)嘗試發送至處理模塊的緩衝區中;
若是緩衝區不滿,直接放置隊尾;
若是緩衝區已滿,則將緩衝區中隊首還沒有處理的消息丟棄,而後將當前消息放置隊尾。
讀模塊:
消息處理模塊讀取緩衝區隊首的消息;
經過判斷該消息的Offset信息是否連續來肯定是否有消息丟失;
若是發現消息丟失,直接從存儲系統「追讀」丟失的消息,直到追上緩衝區隊首的消息。
讀寫分離的好處是,網絡抖動不影響其它節點,局部故障也不放大,不會出現處理快的節點一直在等慢的節點等。
有狀態計算
Map-Reduce-Merge模型,Map和Reduce約定在Batch內的一個Map操做和aggregate的一個reduce操做,語意和Map-Reduce徹底兼容;用戶只須要在Merge裏面去寫用戶邏輯,所有是由增量計算框架來維持,輸入這個Value是本次Reduce的結果,用戶只用把oldValue和這個value進行合併操做而且返回新的值,做爲下一次的oldValue傳。
Checkpoint
看成業的併發數增加時,必定程度上,任務的併發程度的增加已經受限於Hbase的能力,尤爲是隨機讀的能力,因此對整個系統的scale ability是有限制的。
對此,咱們引入了一個內存增量的snapshot機制。用戶能夠指定固定批次的數據,在這個批次內的對於OldValue和state的修改,徹底都在一個增量的snapshot,而這個snapshot在內存裏頭, Merge是update,它徹底是在增量的snapshot內完成,而系統這時持續地引進會產生大量增量的snapshot,這時系統會在內部啓動一個checkpoint的線程,它會順序地將這些snapshot選擇性地進行Compact,Compact後將這個內存的snapshot持久化,批量地刷入到盤古,刷入到一個全局的快存儲。
這樣的機制既保證用戶在調用Merge這個函數的時候,基本上都在操做內存,而整個系統的scale ability不依賴於其餘第三方的可靠存儲,而系統將snapshot的checkpoint是在異步的後臺進行。
並行DAG
爲了克服datascale以及增長系統的時效性,整個DAG徹底是一個並行的DAG。
那進行一個簡單的建模:假設有N條數據,M個資源,共有n個module,第i個module的吞吐爲OI,調度的資源數爲Pi。
圖中能夠看出,在理想狀況下,它們完成的延時是一致的。
但事實上徹底不是。限制時下的物理模型遠遠比這個複雜,串行的模式的優點是模型簡單、吞吐高。劣勢是數據時效性和數據傾斜對系統的總體延時傷害。因此串行模型是面向吞吐、兼顧延時。
並行DAG優點是數據時效性好、對傾斜友好。可是它的建模很是複雜,調度也是很是複雜。
並行模型是面向延時而兼顧吞吐的。
搶佔式調度和資源隔離
整個流計算是個longlive的進程,因此業界以前的調度系統針對任務結束後進程回收的狀況很明顯再也不適用,那麼離線裏面,不管是Yarn仍是fuxi,都不能適應長進程的任務調度。
如今有一個開源項目叫Slider,它在某種程度上嘗試去解決這個問題。在線系統的調度與離線系統的調度差別性是很是大的,咱們須要解決的問題還有不少不少。
在隔離維度上,用戶程序使用的Memory、Network、CPU(隔離難度依次遞增),不須要隔離本地IO訪問(不允許用戶程序訪問本地IO),框架使用的資源,經過消息「流控」來限制。
而Memory上,Java程序經過啓動jvm時的-Xss參數設置;C\C++程序經過按期查看linux下/proc/pid/status,超過上限後,限制消息輸入;Network經過linux系統的iptables + tc模塊。
CPU經過linux taskset命令將進程綁定到某一具體CPU上,同一CPU上多進程依然會發生搶佔資源。
Failover機制
整個流計算的Failover容錯機制,Batch是容錯的最小單位,是數據跟蹤的最小單位,是輸入輸出的最小單位,是控制的最小單位;整個容錯分爲源頭重建和節點重建兩種,全量輸出,無外部互相依賴,跟蹤消息與消息體量級。
離線跟蹤、流式跟蹤、在線跟蹤,徹底在實現方法上、策略上不同。
那麼有狀態計算的Failover的checkpoint,它的內存重建,你們能夠關注開源的tachyon,在整個Failover的機制設計方面,有運行時效率和恢復時效率的一個tradeoff,包括如何避免雪崩,這些都是在容錯機制上要考慮的重點問題。
綜上所述,整個系統是在不斷作TradeOff:
吞吐與響應時間的TradeOff
實時性與數據鏈路的不可控的TradeOff
非冪等操做與數據鏈路的不可控的TradeOff
精度與成本的TradeOff
恢復成本與運行時成本的TradeOff
全鏈路與系統邊界的Tradeoff
需求多樣性與平臺一致性的TradeOff
不一樣計算場景不一樣技術體系的TradeOff
StreamSQL
streamSQL支持用SQL同樣的語意來表示,讓用戶使用SQL來操做流計算。streamSQL提供了5個基本原語:Map、Reduce 、Shuffle 、Union和Merge。咱們也實現了一些高級算子,用戶能夠去擴展高級算子,包括Topk、distinct 、Join 、windows。
如圖所示,最底下的引擎是整個流計算的一個並行DAG;MRM層最主要的部分分爲消息控制、容錯以及計算模型;在此之上定義了算子層;算子層再往上是SQL層,SQL層分爲SQL解析、制定邏輯執行計劃、根據拓普運行狀況和原信息進行物理執行計劃的優化和SQL的改寫。
那麼咱們能夠定義咱們的源表,也就是數據源,你能夠create一個stream table。用戶還能夠定義本身的維表、臨時表,臨時表做爲一個SQL的極聯存在,它定義了內部數據流的一個Schema,實際上它是不存儲任何的數據,只是作串聯上下游的邏輯,構造複雜DAG。
用戶除了寫SQL以外,還能夠自定義函數算子來實現它的邏輯。
StreamSQL的系統架構如圖所示,分紅gateway層、控制集羣層和worker執行層。
用戶看到的是統一的邏輯集羣,咱們提供了開發平臺、Web UI、監控報警以及profiling 和Metric子系統等。
延伸
在實際業務場景中,會發現不少不少的問題等待咱們去解決,好比:
沒法作任務之間的複用數據
完成業務須要各類計算模型
多個系統融合
系統之間沒法共享數據
離線與在線的鴻溝依然明顯
以上就是跟你們分享的流式計算和增量計算的關鍵技術點,謝謝你們!