輕量級大數據引擎

輕量級大數據引擎

內容來源:2018 年 1 月 27 日,潤乾軟件創始人蔣步星在“TECH INSIGHT 暨 ArchData技術峰會成都站”進行《輕量級大數據引擎》演講分享。IT 大咖說作為獨家視頻合作方,經主辦方和講者審閱授權發佈。

閱讀字數:5125 | 13分鐘閱讀

回顧嘉賓演講視頻及PPT,複製鏈接:http://t.cn/ReWLfTR,即可觀看。

輕量級大數據引擎

摘要

本次演講介紹了輕量級大數據計算的各方面優勢,後續通過分析輕量級大數據引擎——集算器中的實際案例進一步展示了具體細節。

輕量級大數據計算

沉重的大數據計算

現在的大數據平臺有個明顯的問題就是越來越沉重。一方面單機性能不再被關注,而是轉向集群規模的堆砌,硬件方面則儘可能的避開外存計算困難,指望巨大的內存。另一方面框架的體系越發龐大複雜,試圖包羅萬象。

輕量級計算需求

從技術角度來看大數據的核心主要是快速的計算以及性能的提高。這兩點其實並不一定只在大數據量的情況下才有需求,即使是幾G,幾十G這樣的規模在高併發的情況下也需要快速的計算和高性能。而且對於臨時性的數據處理也不適合建設大數據平臺。

大數據計算開發難度大

目前很多大數據平臺都將努力的方向轉向了SQL,因為它是性能比拼的主要性能。一般我們在學習的時候使用的SQL大多在3、5行之內,而實際開發過程中碰到的可能更多是3、5百行的SQL語句,優化SQL性能其實幾乎無助於降低這種SQL的開發難度。這時就會導致仍需大量底層的編碼,要經常編寫UDF。其實提高性能本質上是降低開發難度,如果複雜運算的自動化優化靠不住,那麼就需要快速編寫高性能的算法。

集群透明化

現在的大數據平臺也在努力實現集群的透明化,讓單機和集群有更高的一致性,提高代碼的兼容性,一定程度上降低開發難度。但是在集群不是很大的時候並不一定能獲得最優的性能,因為高性能的計算方案因場景而異,其中有些可能是相互矛盾的。且透明化只採取最保險的方法,一般是這些方法中性能較差的那個。

輕量級計算的技術特徵

輕量級計算主要有這樣一些特徵。首先它是面向過程計算,強調可集成性;其次數據源是開放的,並不一定都是在數據庫中;另外它更注重單機優化,會盡可能的壓榨單個機器的計算能力,然後才會考慮集群。最後使用的時候要在集群透明和高性能之間進行權衡,比如節點文件存儲,不用網絡文件系統;多個單機運算,不用統一集群框架。

漏斗運算舉例

問題解釋

輕量級大數據引擎

電商漏斗分析能夠幫助運營人員分析多步驟過程中每一步的轉化和流失情況,上圖展示了依次觸發登錄、搜索商品、查看商品、生成訂單事件的人群轉化流式情況。

關鍵點

關於上述的功能實現有幾個關鍵點。第一是時間過濾,一次性抽取所有階段的數據是沒有必要的,我們所關心的往往是某一個時間段內的事件數據。第二是時間窗口,即目標事件得在規定時間內發生才算有效。第三目標事件要具備有序性,如先瀏覽商品後放入購物車,反之則不算。最後事件屬性也需要過濾,比如我們目前只統計某一品牌的商品。

以上關鍵隱藏著幾個難點。首先是事件窗口跨天,比如2017年1月1日12點至2017年1月6日12點也被當做5天。其次是目標事件的順序不確定,因為是由參數決定目標事件的順序,因此可能會出現“瀏覽商品”->“放入購物車”,也可能出現“放入購物車”->“瀏覽商品”。另外是事件屬性不確定,瀏覽商品時間有brand屬性,登錄事件可能啥屬性都沒有,而屬性又是以json串的形式存在。

傳統計算方案

針對以上這些問題,顯然採用SQL是無法解決的,有序計算是SQL的軟肋,因此不適合寫這類過程計算。常規的做法是使用UDF,毫無疑問這種方式理論上可以提高性能,但是開發工作量太大了,且缺乏通用性,後續的維護非常麻煩。

聚合算法

輕量級大數據引擎

聚合算法可以算是一個比較好的解決方案,上圖為聚合算法(單個用戶)的相關參數定義。M表示的是在規定時間窗口也就是T內,所觸發的最大事件的序號,當M的值等於K,即等於目標事件個數時,就算完成了一個流程。因為整個流程中可能會很多的序列,且還有可能重複,比如出現12123這樣的形式,明顯12的事件觸發了兩次,於是我們就用A來記錄子序列的最大事件序號,這是分別是2和3。S記錄的是當前事件的時間戳,如果S超出了T規定的時間窗口,那麼其所在的序列將被判定為無效。

輕量級大數據引擎

上圖通過集算器編寫的聚合算法的實際代碼。

優化

執行聚合算法需要對原始數據進行一些整理,比如獲取事件和用戶的總數。簡單的做法就是直接使用SQL語句的group_by,因為要同時查詢用戶碼錶和事件碼錶,所以我們需要group_by全部數據兩次。眾所周知大數據運算的性能瓶頸經常在於硬盤,而在關係型數據庫中進行兩次group_by,即使是針對同一個表理論上還是要遍歷兩次,CPU的計算時間可以忽略不計,但是涉及硬盤的時間則不能忽略。

輕量級大數據引擎

為此我們在集算器中設計了一種管道機制。數據在進入遊標進行group的時候,同時會有一種機制將數據壓入到管道中,在管道中繼續進行group,這樣一次運算就能夠輸入兩份結果。

輕量級大數據引擎

這就是實際的代碼和效果對比,很明顯時間縮短了將近一半。

事件ID

整個過程中查詢事件必不可少,原先事件的ID類似於100007、10004、10010這樣的形式,事件順序的判斷依據這些ID編號,這種方式對在數組查找成員相對來說還是很慢的。

輕量級大數據引擎

輕量級大數據引擎

我們的做法是直接將事件ID序號化,預處理階段的時候原先的ID號被轉換為了簡單的id序號,實際計算階段就可以直接根據id來查找到相關的事件。同樣的因為原先的用戶ID也是一長串的數字,所以也應該進行序列化以節省查詢時間。

事件屬性

事件屬性主要存在兩個問題,一是每個事件的屬性項不同,二是屬性是以json串的形式保存。做過調優的朋友應該都知道文本分析的性能都非常差,不僅如此,字符串的比對也很慢,且難以實現複雜的過濾需求,轉成json對象或序表又浪費存儲空間。

輕量級大數據引擎

所以我們將原先的json串形式轉成了數組,造事件碼錶的時候把事件屬性整理好,事先規定好屬性順序,這樣連屬性名也省了,大量節約存儲空間,也加快了讀取速度。

輕量級大數據引擎

這是關於用戶ID,事件ID序號化,事件屬性數組化的所有代碼。

多線程和多進程

解決完以上問題之後,再來看下如何對單機性能進行優化。我們一開始採用的是多線程的方案,因為相對來說比較簡單,但是經過測試發現當多線程並行數達到一定數量後性能卻不升反降。在改用多進程之後,並行數一直升到機器核數,性能始終呈上升態勢。

輕量級大數據引擎

由於我們使用的是java語言,造成這種情況的原因可能是由於多進程的內存事先已經分配好了,之後不會產生衝突。而多線程在分配內存的時候有可能會加鎖、搶資源,其他的線程就需要等待,當內存足夠大時衝突還不會顯現,一旦內存較小就會造成衝突。

單機和多機

輕量級大數據引擎

接下來我們就開始搭建集群。最初做的是4臺機器的集群,每臺機器16個核,採用多進程的方式也就是有64個進程,通過主程序指揮,這裡主機要和64個進程進行通信,相對來說成本有些高。

輕量級大數據引擎

後來我們又重新構建了個三層結構,讓每個機器都有一個子主程序,由子主程序和上端的子程序通訊,這樣機器間的通訊就只剩4次。

總結體會

通過對上述案例的總結,我們有這樣幾個體會。首先過程計算實際上是一個普遍問題,雖然大數據平臺都在努力優化SQL,但卻無助於此類問題的解決,而過度依賴UDF又會使平臺本身失去意義。另外性能優化是個不斷試錯迭代的過程,需要敏捷的開發工具快速的做出原先測試,由於開發太慢UDF就變的不太適合了。

注:關於集算器的相關介紹由於不便描述,請讀者通過文首的二維碼觀看視頻內容。

以上為今天的全部分享內容,謝謝大家!


分享到:


相關文章: