大數據

前端搞報表|數據分析提效全鏈路解決方案

作者:閒魚技術-雲聽

背景介紹

閒魚 2014 年成立,到現在的話已經實現了從 0 ~ 千萬級 DAU 的躍遷,隨著業務的快速發展,業務決策方法緊跟升級。從最原始的經驗驅動到更加科學合理的數據驅動。而要做到數據驅動,需要去做大量的數據分析以及大量的數據報表開發。在整個數據分析鏈路上,存在一些研發痛點:

  • BI資源緊張、響應較慢
  • SQL 查詢速度慢、等待耗時較長
  • 前端與服務端的聯調成本較高
  • 數據類型複雜度高,難以直觀發現有價值的信息

C15-5雲聽-業務大數據可視化如何快速運算分析.002.jpeg

業務現狀

C15-5雲聽-業務大數據可視化如何快速運算分析.003.jpeg

數據分析的現狀流程分為三個部分

  • SQL 開發
  • 應用開發
  • 數據可視化、前臺產出分析報告

完成一整個開發流程,平均耗時要達到 5 天甚至以上。我們一步一步地來看看,每一個研發節點在現階段存在的問題,以及能不能去優化和解決它們。

SQL 開發

負責 SQL 開發的同學工種是 BI,由於BI缺乏工程抽象的概念,導致每個數據開發的需求過來的時候,都需要從 0~1 重新開發 SQL 代碼,但絕大部分數據分析需求的基本邏輯是相似的,沒有可複用性,使整體效率變得特別低。那我能不能在 SQL 的領域增加工程抽象的概念呢?我把 SQL 抽象成一個一個的原子 SQL,前臺只需要指定原則 SQL 的拼裝規則,拼裝層對原子 SQL 進行組裝得到最終的SQL查詢字符串,進而就得到了想要的查詢結果,通過這樣,重複的 SQL 能被沉澱和複用,大大減少了重複開發的時間成本。另外,因為 SQL 查詢的數據量達到億級以上,每次請求的耗時等待需要幾十分鐘甚至以上,用戶體驗非常差,拉低了分析問題的效率,我們的預期是能夠把幾十分鐘的耗時等待縮短到秒級,目前阿里雲推出的一個產品是分析型數據庫,它能夠滿足大數據計算場景下秒級返回查詢結果,我們可以直接拿過來用。

應用開發

負責應用開發的是服務端同學,使用 Java 來開發應用,主要工作是 API 的封裝和數據組裝。前端的定位已經從切圖仔泛化到非常廣闊的領域,我們的能力的邊界在不斷的往外擴,有句老話:“任何可以用 JavaScript 來寫的應用,最終都將用 JavaScript 來寫”。我們為什麼不把這一層應用直接用 Serverless,用 FaaS 的能力把它實現掉呢?

數據可視化

前端同學負責最後的數據可視化。服務端會跟前端約定透出的數據格式,服務端透出什麼樣的數據,前臺默認會進行全量的數據展現,這樣就會有一個問題,特別是在閒魚的業務場景,舉一個 Case:要展現一個數據指標波動的趨勢圖,指標大概有幾十上百種,如果前臺把這幾十上百條曲線同時的渲染出來的話,前臺感受到的就是一團密密麻麻的顏色,他很難去感知到裡面一些有價值的數據波動信息。在這裡面,前臺能不能去做一些事情,去深挖裡面的一些細節呢?能不能把數據裡面顯著性比較高的,可能對業務有幫助的信息,把它提取出來,並直觀展現到前臺呢?

技術方案

C15-5雲聽-業務大數據可視化如何快速運算分析.004.jpeg

基於以上的思考,我設計了這樣的一套技術方案,分為 3 層:

  • 數據層
  • 服務層(FaaS)
  • 展現層

整體邏輯是展現層會上報 DSL(一個結構化的描述)到 FaaS 層,FaaS 層會經過一層 SQL 拼裝、生成的邏輯,把最終的 SQL 放到數據層去做查詢,數據層把查詢到的結果返回到 FaaS 層,FaaS層 再經過數據加工把數據回傳給前臺做可視化展現。

我們再 detail 的往下看,數據層提供的能力圍繞兩點,就是提供滿足分析需要的業務數據,並且使能夠更方便地管理所有底層數據,這部分依賴 BI 同學協作一起去完成。而其中的數據存儲位置,會在兩個位置,第一個是離線數據表,原始數據通過離線計算,定時任務調度去進行數據清洗,存儲到了離線數據表,然後離線數據表再通過數據集成,把數據同步到我們的分析型數據庫裡面。

FaaS 層的邏輯包含:提供基礎的監控能力,包含了權限控制、日誌管理,以及定義標準的查詢 API 的出入參,還有數據加工。在應用邏輯抽象這一塊,將可複用能力抽象到 SDK 裡面。 SDK 實現的關鍵點是 4 點:

  • 設計了一個數據管道的模式,為什麼要設計這種數據管道的模式?是因為整個數據分析的流程,往大了拆可以拆成三大塊,分別是數據獲取、數據加工跟數據可視化。整條鏈路像一個數據管道流,為了讓整個的數據流處理流程更加的靈活與可插拔,設計了這樣一套 pipeline 數據處理模式
  • 知識庫,在應用初始化的時候,會去自動識別所有的底層數據集,對底層數據集的數據類型進行分類,並且生成對應的語義化信息,知識庫會作為我們整個解決方案的基石,為後面的整個的數據加工跟語義化轉換處理提供一個非常重要的能力
  • SQL 生成器就是我在上面提到的,我把 BI 同學寫的 SQL,以原子粒度抽象並沉澱起來,前臺傳入 DSL 去描述組裝規則,組裝之後,會有一層動態編譯層與  AST 語法解析的邏輯,來生成最終的一個 SQL 字符串
  • 數據加工。前臺可視化圖表的輸入數據是可被抽象的,這裡做的事情是把 SQL 查詢的結果跟前臺可視化圖表的標準數據源,做一層數據格式轉化,而轉換的過程是抽象的,可以理解為是一個黑盒子,對前臺來說,它不需要去兼容各式各樣的數據格式。

展現層目前提供的能力是數據看板,在底層提供了智能圖表渲染的能力。智能圖表渲染分為兩大塊:

  • 圍繞閒魚的業務場景,定義了一系列能夠更凸顯業務波動信息的,對業務有價值的數據的可視化圖表渲染方式,並把它抽象到我們的圖表庫裡面
  • 引入算法能力,對數據進行智能提取,像顯著性提取等類型的算法能力,把有價值的信息更直觀的強化給前臺用戶,把一些可能對業務沒什麼價值的信息,在可視化渲染時弱化

服務層 FaaS

C15-5雲聽-業務大數據可視化如何快速運算分析.006.jpeg

服務層 FaaS 基於集團內部提供的 Midway Faas - Serverless 開發框架。在底層抽象了一系列的 BaaS 基礎服務,包含數據庫查詢、權限校驗、日誌上報、知識庫。

前臺入參通過 DSL 解析之後,會再進一步細分為幾個局部 DSL,每個局部的 DSL描述了 SQL 的具體拼裝規則,針對每個局部的 DSL 會執行動態編譯的邏輯。動態編譯會生成 SQL 字符串中間產物,再對中間產物進行 AST 語法樹解析,去判斷有哪些 原子 SQL 索引了同樣的表、同樣的分區、不同的字段,把重複的原子 SQL 進行合併,合併之後會得到最終的 SQL 字符串,將 SQL 字符串傳入到數據庫查詢得到查詢結果。
在閒魚業務場景中,用到最多的是: X 軸、Y 軸的業務圖表,像分佈圖、趨勢圖,以及 Excel 明細這種二維數組的可視化圖表。數據加工負責把 SQL 查詢的結果,進行數據格式轉換。

完成數據轉換之後再繼續完成數據語義化的處理。在存儲表的時候,為了減少存儲成本,會要求存儲圖表的存儲量儘量小,在存表的時候會用 Number 去代表一些 String 類型的表達。比如說:是否發佈會用 0 跟 1 去表達“否 / 是”。但在前臺可視化的時候,如果直接把 0 跟 1 透出到前臺,對於運營、產品來說其實是一臉蒙逼的,他需要花費一定的理解成本來進行思維轉換。我做的一個事情是:在數據加工的邏輯裡面,插入一個語義化的處理,基於之前自動生成的知識庫,先做 SQL 查詢的數據結果的數據加工,再進行一層語義轉化,把 0 跟 1 轉換成“否 / 是”,最終把這部分數據通過接口返回給前臺。

前臺智能圖表渲染

C15-5雲聽-業務大數據可視化如何快速運算分析.009.jpeg

這裡是一個更加直觀的示例圖。畫紅線的部分是下面放大的部分。如果只看上面那張圖,其實看不出任何有價值的信息。因為 Y 軸被拉大了,導致局部的指標變化被抹平,直接看的話會認為這些指標沒有任何波動。對業務來說,它需要關注的是波動、突變的部分。如果把這些信息在可視化的時候抹平了,用戶發現問題的窗戶其實基本上被你關閉了。這裡面智能渲染做的事情,是通過算法加工的邏輯做顯著性提取,把波動明顯的、對業務有參考價值的數據優先展現出來,其他選擇性地弱化處理。右邊是實現的代碼片段,整體的實現邏輯是去遍歷遞歸所有的 X 軸 Y 軸,檢查有交集的部分以及 Y 軸波動區間範圍。

成果

C15-5雲聽-業務大數據可視化如何快速運算分析.008.jpeg
對開發同學來說,只需要把 DSL 描述清楚,整個 dashboard 就直接渲染出來了。
前臺展現側,會透出 SQL 組裝的部分口子,用戶可交互定製修改,並在秒級內就獲得及時反饋(參照上圖左邊),要進一步分析的話,可以去定製想要查看的人群、過濾的人群、維度、標籤,一層一層下鑽分析,對用戶來說,無論是效率還是發現有價值信息的體驗上都有非常大的提升。
整體來說,成果如下:

  • 支持 SQL 靈活組裝,實現了圖表智能渲染
  • 由原本可能 5 人日的研發成本縮短到 0.5 人日
  • 實時計算、秒級返回(1.7 億條數據查詢耗時1062 毫秒)

未來展望

未來,我們將進一步升級,使整個數據分析流程實現 Low-Code 甚至 No-Code ,前臺通過簡單的拖拽即可實現從源頭獲取數據、完成數據加工、數據可視化的步驟、生成數據看板,並深度探索前端智能化的方向,幫助業務更快定位問題、發現潛在問題,輔助業務決策,支撐業務快速發展。

Leave a Reply

Your email address will not be published. Required fields are marked *