雙11數據大屏背後:大規模流式增量計算及應用(附資料)
首先從理解什麼是數據流開始今天的分享,其實在真實的世界中,大部分的數據都是連續產生的數據流,比如手機上產生的GPS信號、用戶在互聯網上的行為、在線搜索、用戶的點擊、社交網絡分享、即時通信以及一些傳感器和物聯網設備采集的日誌信息等,這些數據都是連續產生的,自然就形成了數據流,在這些數據流產生以後,在很多場景下對於數據流的實時分析就會產生很大的價值。
接下來從大家比較熟悉的數據場景切入,比如大家經常會關注的股市情況,股價的波動其實就是實時數據的分析和聚合,除此之外大家在日常生活中還可能比較關心天氣預報,可能會根據實時的信息來看比如當前的台風的情況,這些都是大家習以為常的,也已經深入大家生活的實時數據分析。
而隨著實時數據源的越來越多,實時數據的規模也越來越大,可以應用的場景也越來越多,實時數據的應用也正在往更多的領域深入。比如像每年的天貓雙11全球狂歡節,阿裏巴巴就有一個實時大屏,左圖上是2015年的情況,當時在第35分鍾的時候就已經有了200億的銷售額,同樣的2016年也是一樣,所有的交易數據都會在秒級之內反映在數據大屏之上,再比如在2015年還有模擬的一個地球,可以看到從賣家到買家的訂單都會被實時地刻畫出來,這在商業領域將會給大家一個非常直觀的印象,也可以用於輔助商業決策。
特別是在安全以及監控這些領域,數據有時候除了用於看以外還可以預先設定很多規則,基於流計算的“規則引擎”提供了傳統的安全監控係統無法提供的海量數據處理能力,根據這些規則就可以省去很多的人力勞動,可以自動化地進行報警,利用大規模分布式集群實時計算和分析監控數據,避免人肉數據檢查的低效,有效擴大監控範圍,提升監控時效。這方麵目前有很多的應用,比如像監控電網的運作等。
除了判斷簡單規則以外,還可以通過實時分析數據去發現一些規律,去實現更多的機器智能。這裏舉的是阿裏巴巴幫助協鑫光伏的一個案例,協鑫光伏是一個專門加工太陽能電池的企業,它的設備都非常複雜,上麵的每個設備都有幾百個傳感器,加起來就有成千上萬路信號輸入,如果通過人去理解傳感器的行為,去檢測或者預測哪一個設備將會發生故障再去更換,這中間的延遲就會造成很大的浪費,也就會導致次品率上升的問題。而通過實時的數據分析加上人工智能的算法最終實現了機器自動預警和判斷,這樣不僅提高了工作效率,甚至還能夠預先自動提示操作人員對於設備的某些部件進行更換,最終實現對於良品率的提高,進而提高企業的收益。
更進一步除了對於簡單結構化的數據的分析,實時分析還可以運用到更廣泛的場景,阿裏巴巴目前正在進行的一個項目就是城市大腦,就是將杭州所有城區的道路攝像頭的視頻信息做實時分析,用不同路口的視頻信息來檢測人和車的行為,以此來幫助城市更好地管理和優化交通,為解決城市擁堵問題帶來很大的價值。
未來,實時數據分析將會越來越多地從我們所熟知的領域進入我們未知的領域,基於實時數據分析的應用的創新也會給我們的生活帶來越來越多的變化,這將是激動人心的大趨勢。
那麼從流式數據處理背後的係統架構去看這個問題,實際上實時的數據處理對於大規模大數據的處理係統帶來了大規模的高要求的挑戰。因為數據是實時產生的,但是由於成本原因或者處理能力的問題,數據一般采取“先存後算”的架構,傳統的架構上數據會在分布式文件係統中存儲下來,然後再經過批量的計算,比如每天產生一個數據報表,這就是傳統的數據處理的一套工具鏈。
而在新的要求更加實時的流式數據處理中,原來的“先存後算”的架構顯然是無法滿足要求的。對應的對於實時數據流的處理則希望能夠隨著數據的產生實時地進行加工處理,能夠實現很高的時效性以及很低的計算延遲,並且實時地幫助各種各樣的場景對於大數據的價值進行挖掘。
如果將流式數據處理係統架構進一步細化,從原來先存後算的架構過渡到這樣一個不依賴於一開始的批量數據存儲而每時每刻都要計算的架構,這中間存在著很多的問題和挑戰。下圖就是將係統架構稍微細化一點的示意圖,對於數據源而言,首先數據是實時產生的,需要通過數據總線將實時產生的數據很低延遲地存儲下來,並且需要傳輸給流計算。但是因為數據量的規模以及數據源端的各種複雜性,這樣的數據總線是要求保證數據的持久化的,而且需要保持很低的延時,同時需要保證規模化,所以需要進行數據切片還需要保證數據的順序。因為產生的數據本身是存在順序的,很多應用對於數據的順序也是非常關心的,所以整體而言對於數據總線部分是存在新的要求的,這些就是關於輸入和數據采集的問題。
在之後會詳細地分析計算這一部分,在這裏先不考慮計算。那麼假設數據通過計算之後能夠產生某種價值和知識,在係統架構的消費端也需要經過改造。這裏舉個例子如果需要將應用改造為實時化的,可能在十幾年之前會需要打印出一個紙質的報表,但是這個紙質的報表在實時處理的今天就無法展示出實時的形態了,所以首先需要進行報表電子化。其次要想實現低延遲的展現,就是從數據計算出結果到能夠讓用戶看到計算結果需要很低的延時,否則在實時決策中的效果就無法達到預期。除此之外,整個實時計算係統是由很多服務構建的,所以計算出來的結果可能需要通過消息隊列連接更多的服務,比如觸發了某個規則引擎中規則,就可能需要調用某一個報警機製,比如發短信來通知用戶,這就需要上下遊更多係統之間的配合。第三個場景就是有時實時計算除了使得之前提到的應用成為可能還有一種場景下就需要數據采集手段的提高,因為存在大量的實時數據不得不以流式地進行預處理做一些篩選,將真正重要的信息存儲下來再去進行離線的更加深入的分析。所以無論是數據的上遊還是下遊都需要大量的改造功能才能使得實時計算成為可能。
後麵將會主要分享一下計算這部分,對於實時計算而言,需要麵對很多的挑戰。
首先實時計算需要很高的性能,需要保持延時和吞吐的平衡,需要很好的擴展性,能夠支持超大集群規模的線性擴展。還需要考慮容錯問題,大家知道在進行批處理的時候產生一個錯誤就需要重新計算,而且容錯這部分還需要考慮低延時。還有因為很多任務可能同時在進行計算,所以也需要保證資源的有效利用。實時任務會一直占用資源,而有一些不同的數據流的輸入速度不同,如何調配資源的共享和隔離也是一個挑戰,除此之外還需要考慮流計算的易用性等等問題。
因為今天分享的主題是增量流式處理,所以在這這些流式計算所麵對的挑戰中選擇一個話題展開來講,今天就主要分享關於實時計算如何編程的問題。那麼什麼是實時計算的編程呢?其實就是去寫一個程序來表達實時處理邏輯,數據是以流的形式進來然後存儲在某個消息隊列中,之後應用再去消息隊列中獲取數據並進行計算,並將數據產生的價值傳輸到下遊的係統中。但是與離線計算不同,實時流式計算需要考慮很大的規模,需要同時並行地運行在很多的CPU上麵,所以流式計算的編程實際上就是對於分布式程序的編程,這其實將會一個比較困難的問題。
而對於實時計算編程的一個簡單的解決方式就是目前大數據方麵非常通用的模型——數據流計算。這裏舉的例子就是2011開源的流計算係統Storm,Storm實現的就是如圖的這樣一個數據流的模型,這裏有輸入流和輸出流,中間存在多階段的計算。
當然知識這裏示例性地分為了三個階段,而真實情況下可能有多個階段,在每個階段上數據並行會有多個計算節點。與批處理不同,數據流模型上麵的數據是流動的,所以每個事件在每個階段都是流水式地執行和觸發的,這就是基本的數據流模型,也是被很多係統所采用的模型。下圖中隻畫出了6個節點,如果在成千上萬的節點上去寫這個程序,如何表達計算邏輯就是比較困難的了。剛才提到過數據並行,所以隻需要為每一個階段編寫一個程序就可以了。圖中包含了三個階段,如果根據Storm的概念來看,其實每個階段的編程接口實際上是非常簡單的,這裏是一個示例,比如X節點實現了這樣的一個interface,實現的函數就是當數據灌給你的時候需要該怎麼做,這是一個非常簡單的接口,如果以這樣一個非常底層的接口去描述實時邏輯,下圖中列舉了一個非常簡單的例子,就是WordCount將輸入的數據切成Word分詞,並根據一些窗口去計算詞頻然後進行統計。一個簡單的WordCount會占用很多的代碼行,圖中是從網上找的一個例子,所以大家可以想象如果一個非常複雜的業務使用基本的接口去寫在某些場景下會是非常困難的。
麵對上述這樣的問題,一個想法就是與離線計算的處理一樣去尋找更高層的語言,所以大家會嚐試著去使用SQL。接下來列舉兩個具體的例子,就是如何使用SQL將比較複雜的拓撲通過簡單的幾行代碼描述出來。
這裏的例子就是前些年一個學術界的係統,可以看到上圖中左邊是使用C#高級語言寫的一個MapReduce的程序,實際上就把每個記錄調用Mapper()函數變成多個隊,之後進行GroupBy()並按照不同的組進行Select並做一個Reducer。這個程序就比剛才一行行去寫要簡單很多,係統也可以自動從類似於SQL的描述性語言去生成右側的DataFlow,右側的數據圖從輸入到MapReduce實際上是兩個階段。另外一個更複雜的例子是分布式排序,可以看到一個非常複雜的問題也可以通過寫非常簡單的語言對於每個Mapper()出來的結果給一個Key進行OrderBy(),右邊在生成計劃的時候可以做非常多的工作。這個例子就是想告訴大家不僅可以用高層語言來簡化對於複雜拓撲的描述,還可以讓拓撲在生成的時候進行很多的優化。這裏稍微解釋一下右邊這個圖,這個圖就是對於數據進行排序,大家可能想象簡單的MapReduce就能夠進行排序,但是在實際的執行情況下為了達到高效,數據的負載均衡是非常重要的,那麼如何保證數據在排序這件事情上是分段均衡的呢?這裏的解決思路就是對於每一份數據都進行采樣,這樣就能對於數據分布進行大致地了解,根據數據分布可以確定數據應該按照什麼的range進行重新劃分,這樣就可以將數據分的比較均勻。如果采樣足夠高效,這部分的時間是值得的,因為這會使得後麵的計算更加高效,計算的並行度和加速比也會變得非常高。以上就是SQL的例子,可以看出,在離線的情況下SQL可以幫助我們簡化編程。
接下來我們再回到在線計算,今天的問題就是如何幫助大家用各種簡單的方式編寫一個流計算的程序,這裏舉的例子是一個離線的SQL語句,那麼如果直接將這個SQL用於流計算會產生什麼樣的問題呢?假設輸入的數據是連續的無窮的數據流,在這樣的情況下大家可以看到有什麼樣的困哪呢,因為Group By需要對於例子中所有的Customer Name進行聚合,也就是需要知道某一個“Mike”購買的全部東西才能進行聚合,但是對於實時連續不斷輸入的流,如何才能知道“Mike”有沒有購買更多的東西呢,怎麼知道什麼時候該輸出呢?其實這裏例子就是想要告訴大家如果簡單地將SQL語句用於描述數據流處理實際上在語義上是無法匹配的,所以這樣例子中的Group By是不會有輸出的,但是如果等所有的數據都輸入之後再進行處理就無法達到低延時的效果了,這就是困難所在。
為了解決上述的問題,大家也都想了各種各樣的方法,但是到目前為止並沒有一個最佳的解法。其中一種方式是使用類似SQL的語言去寫這個問題,但是對其中的一些算子進行修改或者引入一些必要的算子。這裏舉個例子就是join操作,如果在SQL裏麵使用join其實就是將兩個表連接在一起,但是在流式計算中將兩個流join如何才能知道已經流過的數據能不能與當前流中的數據連接上呢,就需要保留太多的數據,所以一種做法就是在join上加一個範圍限定實現時序的join。另外Group By操作的問題就是永遠都無法產生輸出,所以可以弱化它的語意,讓Group隻做分流,不同的用戶進來將會丟到不同的Group中,但是並不在其上做聚合。那麼什麼時候做聚合呢?就是需要在流上引入Window的概念,Window有各種各樣的定義,可以按照幾分鍾或者幾小時進行一次聚合等。總之這一係列算法都是引入類似SQL的語言實現,這個方法是微軟最早出SQL Server的時候就有的流數據庫的語言,目前包括亞馬遜、Storm也在提這種語言,但是這部分還沒有統一的標準,各家都有各家的東西。最近Apache Calcite標準試圖將不同的語言進行統一,形成一套大家公認的流式語言,其實標準化非常重要,不然的話學習成本將會非常高。
上述的方法引入了新的語言,雖然形似SQL,其實流式的SQL與傳統的SQL並不一樣,也需要一定的學習成本。
而實際上今天在真實場景下碰到的流計算SQL並不是全新的邏輯,往往在原來有對應的非流式的處理邏輯存在。下圖中傳統的SQL的背後可能是這樣的一個非常複雜的報表係統,老板給你的要求實際上可能是這樣的,實時流式計算能不能幫助降低延時,實時地產生數據,讓老板時時刻刻看到報表的變化,這樣就是一個非常自然的從原來離線的報表實時化的場景。如果現有一個離線的SQL,如何使其實時化呢?其實一種做法是學習新的SQL進行改寫,這種方法是有可能實現的,而且在很多時候也是一個比較好的做法,那麼有沒有更好的做法呢?
其實再分析一下這個問題就是今天已經有一個離線的SQL,而數據表的數據是有窮的並不是無限的數據,就知道如何在數據集上進行計算。如果數據是一點點流式增加的,想要實現老板的需求其實是非常簡單的,在每次數據增加完就運行一次SQL就可以了,這樣就能夠將中間結果以報表的形式讓老板實時地看到了。這樣看上去就是一個流式計算的過程,但實際上在背後其實在不斷地運行離線的SQL,每次前麵和後麵的數據出現差異也就是增加了一些新的數據時就再運行一次離線SQL。這一頁其實想要講的做法就是從離線的計算變到實時計算是可以通過遞進式的增量計算實現的。
那麼這樣做有什麼好處呢?首先大家不必再學習新的SQL語言了,可以直接使用離線的SQL表達處理邏輯。隻是需要將報表隨著數據的到達不斷地變化就可以了,這就是實時計算,不需要繼續再寫程序。其實這樣做就像下圖中的漫畫一樣,流式增量計算可以產生中間的每一幅畫,但是因為數據是遞增到達的,如果每到一個數據就執行SQL就可以將漫畫中的過程生動地展現出來,這對於很多的商業決策是非常有幫助的。但是這其中存在著很大的技術挑戰,就是如果真的這樣去做,雖然不用寫程序,但是計算量卻是非常高的,因為每到一個數據就需要進行重新計算,就好像漫畫中的每一幅都是需要人工畫出來,工作量就比原來隻畫一幅畫多了很多倍,所以今天麵對的技術挑戰就是如果允許自動增量化地計算SQL,怎樣讓計算機盡可能避免冗餘地實現增量計算,如何將此過程的代價降到最低也就是我們需要麵對的技術問題。以上就是解決流計算編程問題的一個新的思路,即可以用離線計算的思維去描述流計算,將複雜的任務交給係統進行處理。
對於這裏提到的係統,其實阿裏雲有一個正處於公測期間的阿裏雲流計算係統,它提供了SQL描述程序,並提供了非常易用的IDE可以供開發者編寫SQL並使其以流式形式運行起來,開發者還可以在IDE中進行調試和監控運維等工作,計算的結果會根據數據的流式輸入不斷更新結果,並且阿裏雲流計算係統在背後也做的許多的優化,所以消耗的資源比較少,而且不再需要學習新的語言。
阿裏雲流計算係統在阿裏內部被證明是非常有用的,因為阿裏原來在包括電商和離線的數據分析中積累的大量的離線SQL,所以可以回到雙11大屏上顯示的數據實際上就是采用這樣的增量計算的方式產生的,實際上是將最終的報表的SQL分析變成實時的數據報表。而其實係統麵臨著許多的挑戰,雖然大家看到的隻是幾個數據加起來,但是其實在背後可能使用了成百上千台機器,峰值的時候需要麵對達到每秒1億次事件的處理,然後進行各種聚合所帶來的挑戰。
接下來分享一下除了流式編程問題以及目前能夠看到的問題以外的一些展望。未來,實時化是一個大趨勢,以後會有越來越多的實時流數據計算的場景。實際上語言和編程是最難的課題,雖然係統已經很難了,但是語言和編程是比係統還難的課題,需要有足夠的經驗和場景才能夠總結某一方麵的東西。今天分享的時序和流式SQL以及增量計算可能適應某一類場景,但是隨著對於應用理解的深入會產生進一步的改進。流式計算之後會更多地使用到包括實時語音、圖像和視頻監測、在線機器學習、智能分析以及物聯網的很多場景中,很多時候大家接觸的大規模的實時計算可能需要處理的是海量的數據流,數據總量是海量的,而且用戶的查詢邏輯也可能是海量的,特別是物聯網和用戶使用的手機可以自定義想要關心的結果,每個人其實都可以放一個流查詢在雲端運行,處理成千百萬的查詢,而如何把這些查詢盡可能做的高效還存在著很多係統的挑戰。
在最後總結部分就是想和大家分享大規模流式計算可能是大數據應用的一個突破點,這裏麵可能是機會與挑戰並存的。機會就是這其中存在著很多的場景,實際上隨著對於場景理解的深入,從係統的設計以及底層的語言上麵可能有很多的機會和需求要進行重新考慮,當然阿裏巴巴會將很多東西不斷地放在雲上作為雲服務,讓大家不斷嚐試,也希望能夠得到大家的反饋更好地指導下一步該怎樣走。另外就是需要深入領域,和領域相關的專家進行合作,結合真實的場景解決真實的問題。最後還想談一談,在阿裏雲,我們始終擁抱技術的發展趨勢,也期待在這個領域中和大家一起通過技術和應用創新向大數據要更多的紅利。
原文發布時間為:2017-03-20
本文來自雲棲社區合作夥伴“大數據文摘”,了解相關信息可以關注“BigDataDigest”微信公眾號
最後更新:2017-05-22 15:33:29