創業公司做數據分析(六)數據倉庫的建設
文 |?Mr-Bruce
創業公司做數據分析(四)ELK日志系統>>>
創業公司做數據分析(三)用戶行為數據采集系統>>>
創業公司做數據分析(二)運營數據系統>>>
創業公司做數據分析(一)開篇>>>
作為系列文章的第六篇,本文將重點探討數據處理層中數據倉庫的建設。在第二篇運營數據系統一文,有提到早期的數據服務中存在不少問題,雖然在做運營Dashboard系統時,對后臺數據服務進行了梳理,構建了數據處理的底層公共庫等,但是仍然存在一些問題:
- 中間數據流失,計算結果沒有共享。比如在很多數據報告中都會對同一個功能進行數據提取、分析,但是都是各自處理一遍,沒有對結果進行共享。
- 數據分散在多個數據源,如MySQL、MongoDB、Elasticsearch,很難對多個源的數據進行聯合使用、有效組織。
- 每個人都需要非常清楚產品業務邏輯才能正確地提取、處理數據,導致大家都將大量時間耗費在基礎數據處理中。
于是,我們考慮
建設一個適于分析的數據存儲系統
,該系統的工作應該包含兩部分:第一,根據需求抽象出數據模型;第二,按照數據模型的定義,從各個數據源抽取數據,進行清洗、處理后存儲下來。雖然數據倉庫的學術定義有很多版本,而且我們的系統也沒有涉及到多部門的數據整合,但是符合上述兩個特點的,應該可以歸結到數據倉庫的范疇了,所以請允許筆者將本文命名為“數據倉庫的建設”。
下圖所示,為現階段我們的數據倉庫建設方案。數據主要來源于MySQL和MongoDB中的業務數據、Elasticsearch中的用戶行為數據與日志數據;ETL過程通過編寫Python腳本來完成,由Airflow負責任務流的管理;建立適于分析的多維數據模型,將形成的數據存入MySQL中,供數據應用層使用。可以看到,數據倉庫本身既不生產數據也不消費數據,只是作為一個中間平臺集中存儲數據,整個系統實現的重點在于
數據建模
與
ETL過程
,這也是日常維護中的重點。
存儲選型
將數據落地到哪里是首先要考慮的問題,筆者考慮的因素主要有這么幾點:一是數據量大小和增長速度,二是要能實現SQL或者類SQL操作,有多表聯合、聚合分析功能,三是團隊技術棧。可選的技術方案有MySQL、Oracle和Hive,最終選擇了 基于MYISAM存儲引擎的MySQL ,部分原因如下:
- 要不要Hadoop? 生產業務數據庫與用戶行為數據增長均比較緩慢,預計在接下來的一年里數據倉庫的總存儲量不會超過500GB 。因此現階段接入Hadoop的意義不大,強行接入反而會降低工作效率。而且團隊主要技術棧是Python,使用Python操作Hadoop本身就會有性能損耗。
- 為什么是MySQL? 相比Oracle,團隊對MySQL更加熟悉,所以筆者更多的考慮是選擇MySQL的哪個存儲引擎:Infobright vs. myisam vs. innodb。Infobright引入了列存儲方案,高強度的數據壓縮,優化的統計計算,但是目前已經沒有社區版了,需要收費。拋開底層存儲的區別,myisam與innodb在特性上的區別主要體現在三個方面:第一,引用的一致性,innodb有外鍵,在一對多關系的表之間形成物理約束,而myisam沒有;第二,事務,innodb有事務操作,可以保證一組操作的原子性,而myisam沒有;第三,鎖級別,innodb支持行鎖,而myisam只支持表鎖。對于外鍵與事務,并不是數據倉庫需要的,而且數據倉庫是讀多寫少的,myisam的查詢性能優于innodb,因此myisam成為首選。
數據建模
根據數據分析的需求抽象出合適的數據模型,是數據倉庫建設的一個重要環節。所謂數據模型,就是抽象出來的一組實體以及實體之間的關系,而數據建模,便是為了表達實際的業務特性與關系所進行的抽象。數據建模是一個很寬泛的話題,有很多方法論值得研究,具體到業務上不同行業又會有不同的建模手法。這里主要結合我們的實踐來簡單地談一些認識和方法。
目前業界有很多數據建模的方法,比如范式建模法、維度建模法等等。遵循三范式,我們在做業務數據庫設計時經常會用到,這種方法對業務功能進行抽象,方便功能擴展,但是會額外增加分析的復雜度,因此筆者更傾向于維度建模法。
維度建模法
,是Kimball 最先提出的概念,將數據抽象為事實表與維度表兩種,而根據二者之間的關系將整體的模型劃分為星型模型與雪花模型兩種。這種建模方法的優勢在于,根據各個維度對數據進行了預處理,比如按照時間維度進行預先的統計、分類等等,可以提高數據分析應用時的效率,是適于分析的一種方法。具體來看看幾個概念:
- 維度表與事實表 。維度表,描述的是事物的屬性,反映了觀察事物的角度。事實表,描述的是業務過程的事實數據,是要關注的具體內容,每行數據對應一個或多個度量事件。比如,分析“某地區某商品某季度的銷量”,就是從地區、商品、時間(季度)三個角度來觀察商品的銷量,維度表有地區表、商品表和時間表,事實表為銷量表。在銷量表中,通過鍵值關聯到三個維度表中,通過度量值來表示對應的銷量,因此事實表通常有兩種字段:鍵值列、度量值列。
- 星型模型與雪花模型 。兩種模型表達的是事實表與維度表之間的關系。當所有需要的維度表都直接關聯到事實表時,看上去就是一顆星星,稱之為星型模型;當有一個或多個維表沒有直接關聯到到事實表上,而是通過其他維度表連接到事實表上時,看上去就是一顆雪花,稱之為雪花模型。二者的區別在于,雪花模型一定程度上降低了信息冗余度,但是合適的冗余信息能有效的幫助我們提高查詢效率,因此,筆者更傾向于星型模型。
- 基本的維度建模思路 。維度建模的基本思路可以歸納為這么幾點:第一,確定主題,即搞清楚要分析的主題是什么,比如上述的“某地區某商品某季度的銷量”;第二,確定分析的維度,準備從哪幾個角度來分析數據;第三,確定事實表中每行的數據粒度,比如時間粒度細化到季度就可以了;第四,確定分析的度量事件,即數據指標是什么。
舉個例子,業務場景是:一款做連鎖企業招聘工作的產品,比如為麥當勞的所有連鎖門店招聘員工,現在要分析“每家門店的招聘情況如何?”。結合具體業務,我們引入六個維度:時間維度、地區維度、品牌維度、門店維度、職位維度、申請渠道;數據指標上,主要有申請工作人數、申請工作次數、聘用人數、拒絕人數,每個指標分別有增量值和總量值兩種;數據粒度上,時間維度細分到以小時為單位,地區維度細分到市一級。下圖所示便是相應的星型模型,有三點值得一提:
- 可以看到我們只建立了四張維度表,地區維度和渠道維度是直接以字符串的形式放到事實表中的。這是維度設計中經常遇到的一個問題:如果這個維度只有一個屬性,那么是作為單獨的一張表還是作為事實表的一部分?其實并沒有完全對與錯的答案,只有是否適合自己的答案。這里,城市與渠道的信息并不會發生變化,所以放入事實表中可以避免聯合查詢。
- 建立了統一的時間維度,可以支持各種時間統計方案,避免在查詢時進行時間值運算。
- 在品牌維度、門店維度、職位維度三張表中,都有prod_xxxx_id的字段,其值是產品業務數據庫中相應數據的id,作用是為了與業務數據庫中的信息進行同步。當業務數據庫中的相關信息發生變化時,會通過ETL來更新數據倉庫中的信息,因此我們需要這樣的一個字段來進行唯一標識。
ETL
ETL這塊,由于前期我們做了不少工作來構建底層數據分析公共庫,能有效的幫助我們進行數據抽取與處理,因此,現階段還沒有引入諸如Kettle這樣的開源工具,主要采用編寫Python腳本來實現。這里主要談談增量更新機制與任務流管理兩個問題的策略。
1. 增量更新機制
增量更新的背景是這樣的:第一,上面有提到,對于可變的維度表,我們添加了prod_xxxx_id字段來唯一標識,實現信息覆蓋更新。對于事實表,為了反映歷史狀態,表中的數據通常是不可逆的,只有插入操作,沒有刪除或者修改操作,表示在過去一段時間內完成的事實業務數據,更新的方法就是插入新的數據。第二,ETL通常是近實時的,需要依賴schedule觸發更新,因此每次需要更新的信息就是上一次更新時間與當前時間之間的變化數據。筆者采用的策略是:
- 建立一張temp表,表中有last_update_time與etl_name兩個字段;
- 每次更新時,首先查詢出相應的etl_name的最近一條記錄,取其中的last_update_time作為起始時間,取當前時間為結束時間;
- 抽取數據源中在這段時間內變化的數據,作為ETL過程的輸入,進行處理;
- 更新成功時,插入一條數據,last_update_time為當前時間。
2. Airflow任務流管理系統
在早期數據服務中,我們主要依靠crontab來運行各個任務,隨著業務增多,任務的管理變得越來越吃力,體現在以下幾方面:
- 查看任務的執行時間和進展不方便。每次需要查看某個任務的執行情況時,都要登錄到服務器上去查看命令行的執行時間、log在哪里,通過ps來查看當前進程是否在運行等等。
- 任務跑失敗后,沒有通知與重試。
- 任務之間的依賴關系無法保證,完全靠預估,然后在crontab里設定執行時間間隔,經常出現上游還沒有處理完,下游就啟動了,導致臟數據的產生。
于是,我們開始考慮引入一個任務流管理系統,基本想法是:第一,要能解決上述的問題;第二,最好能與Python友好的兼容,畢竟團隊的主要技術棧是Python。經過調研,發現Airflow是當前最適合我們的。 Airflow 是Airbnb公司開源的一款工作流管理系統,基于Python編寫,兼容crontab的schedule設置方法,可以很簡單的描述任務之間的邏輯與依賴,并且提供了可視化的WebUI用于任務管理與查看,任務失敗時可以設置重試與郵件通知。這里貼一張官方的截圖來一睹其風采。
Airflow有三個重要的概念:DAG、Task和Operator。DAG(directed acyclic graphs),有向無環圖,用來表示任務的依賴結構;Task表示一個具體的任務節點;Operator表示某個Task的執行體是什么,比如BashOperator是執行一個Bash腳本,PythonOperator是執行一段python代碼等等。使用Airflow,首先要編寫對應的任務腳本,通常腳本需要做三件事:第一,描述DAG的屬性(比如schedule、重試策略等),第二,描述Task屬性(比如Operator是什么),第三,描述Task的依賴情況。進一步的認識可以參考官方文檔。
以上便是現階段我們的數據倉庫發展與建設方法,雖然比較簡單,但是目前基本能滿足需求。隨著數據規模的增長和業務的復雜化,未來還有很多路要走:如何合理的建模?如何有效的利用數據?如何提高數據分析效率?期待更多的挑戰!
?
End.
轉載請注明來自36大數據(36dsj.com): 36大數據 ? 創業公司做數據分析(六)數據倉庫的建設