2020年初,疫情讓許多創(chuàng)業(yè)公司緊急剎車,這無疑是一次極限壓力測試。它讓所有企業(yè)都知道,“黑天鵝”隨時都會來,反脆弱能力很重要。
神策數(shù)據(jù)的反脆弱能力源于夯實的基本功。在過去的5年里,神策數(shù)據(jù)服務了1000余家企業(yè)。依托底層數(shù)據(jù)采集、建模、分析、應用的標準化的用戶分析體系,神策數(shù)據(jù)使得超過EB級別的海量數(shù)據(jù)能夠高效處理,并以秒級的響應速度,服務并驅動千余家企業(yè)的發(fā)展。
期間,神策數(shù)據(jù)定義了公認的行業(yè)最高標準:30分鐘完成私有化部署、單日入庫千億條數(shù)據(jù)、億級日活實時在線分析……至今,同行業(yè)內無一企業(yè)能夠企及。
在當下的窗口期,神策數(shù)據(jù)視之為修煉內功的最好時期。復工兩個月后,神策數(shù)據(jù)又一次震動行業(yè):重構分析引擎,進入2.0時代!
為什么要優(yōu)化分析引擎?
神策分析引擎是神策數(shù)據(jù)產品矩陣的核心組件之一,它負責神策分析中的所有分析模型的計算執(zhí)行,此外,它還支撐了神策用戶畫像平臺的標簽人群的計算、神策智能運營系統(tǒng)中的受眾選擇等功能。
一般來說,它也是神策系統(tǒng)中最大的硬件資源(CPU、內存)占用方。因此,對它的性能進行持續(xù)優(yōu)化一直是我們的工作重點。
神策數(shù)據(jù)作為一家以私有化部署為主的大數(shù)據(jù)軟件服務提供商,隨著客戶群體在不斷增加,客戶的數(shù)據(jù)量級也在快速上升,目前,神策數(shù)據(jù)平臺所處理的日新增數(shù)據(jù)量已經(jīng)高達1500億條,而神策數(shù)據(jù)的分析引擎每天處理的數(shù)據(jù)條數(shù)則在數(shù)萬億級別。
性能的持續(xù)優(yōu)化一方面可以顯著的提升產品使用體驗的提升,而從另外角度看,也意味著我們的客戶可以以更低的硬件成本來承載系統(tǒng)的運行。
神策分析引擎2.0圍繞存儲、查詢執(zhí)行、查詢調度進行了全面升級與優(yōu)化,下面詳細介紹。
一、存儲的優(yōu)化
雖然我們的最終目標是為了優(yōu)化查詢的性能,但是數(shù)據(jù)的存儲是查詢的基礎,因此首先我們在存儲方面做了一系列的優(yōu)化,其中最主要的是我們重構了事件(Event)數(shù)據(jù)的存儲方案,此外我們也在數(shù)據(jù)的合并策略等其它方面做了優(yōu)化。
重構事件數(shù)據(jù)的存儲方案
神策數(shù)據(jù)平臺中對于事件數(shù)據(jù)的存儲方案在我們之前的文章中有比較詳細的介紹,簡單的說,我們的方案里使用了HDFS+Parquet來存儲歷史數(shù)據(jù)、Kudu存儲實時數(shù)據(jù)的方式,同時按照日期、事件來進行分區(qū),如下圖所示:
這種存儲方案對于導入和大部分的查詢場景都是比較友好的。但是隨著越來越復雜的應用場景,我們也發(fā)現(xiàn)了一些需求在目前的方案下無法得到滿足:
1.在很多復雜的分析場景下,分析引擎需要先對數(shù)據(jù)進行按照用戶、時間進行排序的處理,而由于底層的事件數(shù)據(jù)的有序性很有限,這樣會導致在執(zhí)行查詢的時候需要對數(shù)據(jù)進行臨時的排序操作,消耗比較多的資源。
2.一個典型的應用場景里會存在多種不同類型的事件,這些事件有的需要永久保留、高頻查詢,而有的可能只需要保留比較短的時間周期,或者在一段時間之后就不再高頻使用。
3.雖然大部分的事件都是對歷史的記錄,在入庫之后就不會需要進行更新。但是依然有部分類型的事件需要支持比較頻繁且實時的更新操作,比較典型的如電商的訂單事件,訂單的狀態(tài)往往是需要可變的,如果能實現(xiàn)直接對狀態(tài)的更新會讓很多分析場景更簡單。
為了解決上面幾個問題,我們對事件數(shù)據(jù)的存儲方案進行了一次重構,完成了以下兩個主要改進點:
1.進一步強化了對每個分區(qū)內數(shù)據(jù)的預排序。盡可能的保證數(shù)據(jù)的有序性,這樣可以極大的減少我們在實時分析時需要的重排序時間。
2.支持對于不同事件分桶的數(shù)據(jù)使用完全不同的存儲策略(Storage Policy)這些不同的存儲策略可以使用不同的存儲系統(tǒng)、存儲周期、壓縮算法等。
例如對于常規(guī)的事件,我們默認使用基于本地HDFS+Parquet的存儲方案;而對于低頻使用的事件,我們可以設置定期的歸檔策略,把歷史數(shù)據(jù)放入AWS S3等更廉價的存儲;對于需要支持更新的事件,則采用直接基于Kudu的存儲。
可以看到,新的存儲方案不僅直接支撐了后續(xù)復雜查詢效率的優(yōu)化,還使得客戶在海量數(shù)據(jù)下的存儲成本更加可控,同時,這個全新的設計也為未來更復雜的應用場景預留了足夠的靈活性。
存儲相關的其它優(yōu)化
支持數(shù)據(jù)的實時導入是神策數(shù)據(jù)平臺的重要特性,但是在實時導入的場景下,存儲系統(tǒng)里會不可避免的產生大量的碎片文件,而這些碎片文件則會對查詢的性能有很大負面影響。
在我們之前的設計里,這些碎片文件的合并是由一個定時調度的任務來執(zhí)行,這個任務會持續(xù)的使用固定的資源來進行碎片數(shù)據(jù)的合并,這一方式會導致在系統(tǒng)的使用高峰期占用過多的資源,而在低峰期則可能產生資源空閑。
因此,我們對它的調度策略進行了優(yōu)化,使用動態(tài)的調整與執(zhí)行并行度的方式,以保證在盡可能用滿系統(tǒng)資源的同時,不影響正常的查詢負載。
此外,我們還優(yōu)化了主要數(shù)據(jù)的壓縮算法。在經(jīng)過大量的真實數(shù)據(jù)測試之后,我們發(fā)現(xiàn)使用LZ4/ZSTD的組合方案來替換之前SNAPPY/GZIP的方案,可以在壓縮比不變甚至略有提升的同時,降低數(shù)倍的CPU資源使用。
ZSTD官方的測試結果(https://github.com/facebook/zstd)
最后,我們還對稀疏寬表的數(shù)據(jù)的寫入效率進行了優(yōu)化,這個優(yōu)化對于那些上千個屬性的寬表的數(shù)據(jù)寫入效率有數(shù)倍的提升。
二、查詢執(zhí)行的優(yōu)化
查詢執(zhí)行,一直是檢驗系統(tǒng)是否健壯的試金石。后端存儲的海量數(shù)據(jù),只有查詢引擎足夠強大,才能保證前端風平浪靜地實時查詢,整體平穩(wěn)運行。正如我們之前的文章所介紹的,神策分析引擎是以Impala的執(zhí)行引擎為核心的系統(tǒng)(詳情內容請參考鏈接:付力力:基于Impala構建實時用戶行為分析引擎),因此這部分主要也是對Impala的執(zhí)行計劃以及計算層做的修改。
優(yōu)化基于用戶行為序列的查詢
基于用戶行為序列的查詢是應用場景非常普遍的一類分析需求,神策分析中的漏斗分析、歸因分析、Session分析等功能都屬于這一類。它們的共同點是需要得到每個用戶的完整、有序的行為序列,然后進行一系列復雜的規(guī)則計算。
在我們之前的分析引擎的實現(xiàn)里,受限于底層的數(shù)據(jù)存儲結構,這類查詢每次都需要對幾億至上千億條的數(shù)據(jù)進行重排序操作,雖然我們對這個排序操作本身已經(jīng)做了比較深度的優(yōu)化,但是依然是非常耗時的操作。尤其在內存資源不足的情況下,還會啟用基于磁盤外部排序,這樣整體的耗時會更長。
在一般的數(shù)據(jù)分析系統(tǒng)里,通常解決這類復雜分析問題的思路是進行預計算,即在預先定義好維度、指標的前提之下,把結果提前計算出來并緩存好。不過預計算的局限性是非常明顯的,即很難應對靈活多變的需求。
因此,為了更好的支撐這類靈活的分析需求,我們依然確定了從查詢執(zhí)行本身來優(yōu)化的整體思路,基于上文所提到的存儲結構優(yōu)化,在Impala執(zhí)行層更加充分的利用了底層數(shù)據(jù)的有序性,把全局的內存排序優(yōu)化為了局部的歸并排序,最終使用更少的內存資源和更短的執(zhí)行時間完成了查詢的執(zhí)行。
優(yōu)化前后的執(zhí)行計劃對比
在這個優(yōu)化點完成之后,部分復雜查詢場景的效率提升了10倍,而內存使用則降低到原本的1/5。
查詢引擎的其它優(yōu)化
除了專門針對用戶行為序列查詢的優(yōu)化之外,我們還對Impala的代碼生成(Codegen)技術做了進一步的擴展,讓它在更多的場景下可以使用。
另外還實現(xiàn)了Join表達式下推的優(yōu)化、針對復雜條件表達式的表達式預求值優(yōu)化等,這些優(yōu)化都在不同的使用場景下提升了數(shù)倍的查詢效率。
值得一提的是,由于這些優(yōu)化點中很多并非神策獨有的場景,我們也會把這類通用的優(yōu)化點都提交給Impala社區(qū),其中部分已經(jīng)合并到最新的官方Release版本中。
三、查詢調度的優(yōu)化
查詢性能上的指標提升固然重要,但是對于神策系統(tǒng)的直接使用者來說,在查詢性能提升同時,也更期望有穩(wěn)定優(yōu)異的綜合使用體驗。尤其在數(shù)據(jù)量巨大、硬件資源有限的客觀場景之下,不同查詢的響應時間也會存在比較大的差異,但是我們依然期望可以通過在查詢調度、產品體驗上的一系列優(yōu)化,讓每位用戶都能在一個可預期的時間內,及時得到正確的數(shù)據(jù)分析結果。
查詢資源預估
Impala并不是一個為高并發(fā)或者大量用戶共同使用而設計的系統(tǒng),尤其是在遇到大量高內存消耗查詢的場景下,很容易出現(xiàn)集體失敗的情況。而這種情況之所以出現(xiàn),最主要的問題就在于查詢引擎往往很難準確預估出一個查詢所需要的資源,尤其是內存資源的大小。
只有有了準確的資源預估,查詢的分級調度、排隊、并發(fā)控制等策略才有了執(zhí)行的前提。不過很遺憾的是,雖然Impala最近發(fā)布的幾個新版本也在查詢的資源預估、資源的控制方面做了不少的改進,但是依然不能滿足神策分析這種復雜應用場景的需要。
不過,我們也發(fā)現(xiàn)并非一定需要依賴Impala才能獲取到查詢預估的信息。神策分析雖然是一個非常靈活的數(shù)據(jù)分析系統(tǒng),但是在實際的應用場景下,用戶的查詢模式上依然還是會形成某種規(guī)律。
因此,我們完全通過對已經(jīng)完成的歷史查詢記錄的分析,結合Impala的已有功能,構建出了一個查詢資源預估的模型。這樣,我們可以在任何一個查詢執(zhí)行之前,對它的資源消耗做出相對準確的預估。
有了準確的查詢資源預估,神策數(shù)據(jù)分析系統(tǒng)不但可以告知用戶每個查詢的大致執(zhí)行時長,還可以在查詢資源不足的情況下實現(xiàn)對查詢資源的有效調度,從而避免資源擠兌導致查詢連環(huán)失敗的現(xiàn)象。
在此基礎上,我們還支持對用戶、角色、項目等不同維度的查詢資源進行精細化控制,以滿足集團型客戶在資源控制方面的復雜需求。
異步查詢
大部分場景下,神策分析都可以將分析結果實時返回給用戶,例如在數(shù)秒或者不超過30秒的時間內返回并展現(xiàn)出結果。
但在以下個別場景中,可能需要用戶等待數(shù)分鐘或者更久:
1)查詢的數(shù)據(jù)量特別大,同時查詢復雜度很高,且無法命中緩存;
2)查詢的并發(fā)人數(shù)較多,且無法命中緩存;
3)查詢返回的結果集特別大,例如查詢一個用戶群的列表,返回的結果集可能有幾百兆或者更大。
考慮到盡可能不阻塞用戶的查詢工作,且避免因誤操作關閉頁面導致無法找回之前的查詢結果,我們在產品中增加了異步查詢功能。
針對上述三個場景,允許用戶將此查詢保留至后臺持續(xù)計算。當查詢完成,通過消息通知及時告知用戶查看或下載分析結果。
整體性能提升對比
附上做完上面的所有優(yōu)化之后,我們自己模擬的標準數(shù)據(jù)集下在一些典型場景下的性能提升對比:
神策分析引擎2.0是神策數(shù)據(jù)各產品線和分析模型演進與迭代的基礎,本文提到的部分功能及優(yōu)化點已經(jīng)隨著神策分析新版本的上線覆蓋了數(shù)百家客戶,部分底層架構改動較大的優(yōu)化點則正在小范圍試運行階段,會在未來的兩個月內逐步覆蓋到神策數(shù)據(jù)的所有客戶。
給客戶帶來價值,而價值源于打磨。在神策數(shù)據(jù)內部,神策數(shù)據(jù)視技術實力為根據(jù)地,產品的性能指標一定做到市場最佳,絕不容忍被趕上,哪怕有一丁點苗頭,神策數(shù)據(jù)都會全力以赴,希望通過構建更強大產品性能和功能,讓用戶從數(shù)據(jù)中獲得更深入的數(shù)據(jù)洞察力。
了解更多分析引擎的詳細內容,可關注神策數(shù)據(jù)公眾號,或在神策數(shù)據(jù)官網(wǎng)進行demo體驗。