摘要:美圖擁有十億級用戶,天天有數千萬用戶在使用美圖的各個產品,從而積累了大量的用戶數據。隨着App的不斷迭代與用戶的快速膨脹,產品、運營、市場等愈來愈依賴於數據來優化產品功能、跟蹤運營效果,分析用戶行爲等,隨之而來的有愈來愈多的數據統計、分析等需求,那麼如何應對和知足不斷膨脹的數據統計與分析需求?業務的不斷髮展又怎麼推動架構實現的改造?本文將介紹大數據業務與技術的碰撞產物之一:美圖大數據統計分析平臺的架構演進,但願經過此次分享能給你們帶來一些解決數據業務與架構方面的思考。 php
若是有作過大數據相關開發的同窗應該知道數據統計是一個比較尷尬的事情,第一個它可能不是一個很是有技術含量的事情,對於技術人員的成長來講不是很是好。第二它多是一個比較重複工做的事,須要解決一些簡單的需求的重複工做。java
美圖其實有很是多的App,每一個 App 基本上都會有相應的產品運營、銷售以及數據分析的同窗,這些同窗會提各式各樣數據統計的需求,好比數據報表或者數據分析的需求。這麼多的分析或者說數據統計的需求,在美圖是怎麼解決的呢?今天主要想介紹下在美圖的解決方案,但願你們在平時工做中有遇到相似的問題的話能有一些共鳴之處。程序員
內容主要分三塊,第一部分是統計業務與技術碰撞。通過第一部分的演進之後,咱們有沉澱下來一些東西,有一些思考知道怎麼去解決這些問題,因此第二塊主要是介紹美圖統計平臺架構的實現。第三部分將介紹咱們正在作的事情以及將來的一些規劃。shell
統計業務與技術碰撞數據庫
這基本上是我本身親身的經歷,剛開始一我的作這一塊的業務,會碰到一些有意思的點,可能分三個階段,第一個階段是在項目的初期,咱們是怎麼樣去應對一些產品的初期需求的。第二個階段是當用戶量爆發之後,業務數據源上來之後咱們又是怎麼迭代的。第三是做爲一個有一點追求的技術人員來講,怎麼讓本身去脫離一些業務,獲得一些成長。數組
第一階段——項目初期安全
這個階段特色很是明顯:以美拍爲例,初期總體的數據體量小;統計需求比較少主要是一些基礎的統計指標;產品的迭代很是快,要求數據的統計指標可以快速地跟上產品的迭代速度。架構
這一階段的解決方案在如今看來很是的簡陋:一個是業務的服務端可能會有多個節點,保證可用性,每一個業務節點的服務會打相應的日誌到本地磁盤,而後會經過rsync的方式統一同步日誌到一個數據存儲節點,在這個節點上寫一些簡單的shell或者php腳原本實現統計邏輯,配置相應的crontab來定時觸發統計任務,最終把數據結果存儲到MySQL供展現層調用呈現報表。app
第二階段——快速發展階段框架
當用戶量忽然爆發之後,數據量會不斷的增大,產品運營、數據分析的需求愈來愈多,相應第一個階段的解決方案會存在比較大的問題,主要有幾個:第一個是單點存儲的容量很是有限,第二是計算瓶頸很快就會趕上瓶頸,不少時候統計報表由於計算瓶頸致使報表次日延遲產出,第三是咱們用shell或者php腳原本實現統計邏輯,總體後續的維護成本比較大,須要調整一個統計邏輯或者增長一些過濾條件等都比較不方便。
因此咱們作了一些調整:第一是實現了一套數據採集的系統,負責作服務端日誌的數據採集工做,將數據最終落地存儲到HDFS;第二是前面有提到說存儲和計算的單點問題,因此咱們本身搭建一個Hadoop集羣來解決單點的存儲和計算;第三是基於Hive來解決編寫過多統計邏輯相關的代碼。
第三階段——有追求的程序員
當需求不斷膨脹的時候,做爲一個有追求的程序員會考慮到,重複的代碼量很是多,即便咱們有架一層Hive來寫相應的代碼,最後作一層數據的過濾或者一些聚合。其實每個統計需求咱們都須要寫一個相應的 java 的實現。這個工做量很是的枯燥,也是不斷重複。
一個有追求的程序員的話,可能不會甘於天天作重複的工做。由於在平時接觸業務與實現過程當中,深有體會統計業務邏輯的流程基本上是一致的,因此考慮抽象出這樣一個相對通用的業務處理的流程,基本的流程是從數據源Query出數據,而後作一些業務方面的聚合或者過濾,最終把數據存儲到DB。那在代碼實現層面作了一層抽象,抽象一個統計的組件,包含Query、Aggregator以及DBStore,而後分別有一些不一樣Query和Store場景的實現。當作了一層這樣的抽象之後,相比於前面的方案,生產力仍是獲得了比較大的提高。當時我一我的,一天可以作四五個統計需求,而抽象後一天從瞭解需求開始到實現大概能作七八個統計需求,總體效率有不錯的提高。
美圖統計平臺的架構實現
作了上面的抽象之後仍是有很多的痛點,一個是業務的依賴,指的是咱們作一個統計需求最花時間成本的是去了解數據業務方的需求背景,瞭解他們的產品長什麼樣子或者他們的運營是作了什麼活動,業務溝通背景的成本很是高。第二是即便作了抽象仍是會有一些相應的重複代碼的編碼量,還須要作一個統計的組件選擇相應的query,相應的業務邏輯的處理以及存儲層的DBstore。第三主要是運維成本高,當時上線一個任務須要作一個包到線上,還須要改一些shell等腳本。第四是涉及到我的成長方面,當一我的長時間在作這樣事情的話,對我的的技術成長實際上是有比較大的瓶頸。
基於上面的痛點,咱們來介紹一下咱們是如何解決這些事情的。咱們考慮去作一個平臺,讓業務在咱們這個平臺去使用,咱們提供服務就好。圖 4 是咱們當時作平臺化的大概思路,好比左邊這個業務方有很是多的報表數據需求,也可能有App的數據場景、商業廣告等的數據需求,咱們但願可以提供這樣的一個平臺,業務的數據需求方在這個平臺上面配置他們想要的數據指標,而這個平臺負責數據的計算、存儲,以及最終吐出相應的數據給數據應用方。
更進一步,在作這個平臺時,咱們可能須要考慮如下幾個比較重要的點:第一,咱們可能須要對統計任務有一個比較清晰的元數據描述,能夠描述出這些統計任務的計算方式是什麼樣子,算子是什麼。第二是這個統計任務的數據源來自於哪裏,以及數據須要存儲在什麼地方更合適業務查詢。第三個是須要有一個調度中心來統一調度全部統計任務的執行。第四要確保任務的最終的正確執行。
基於上面這幾個點,考慮須要有一些不一樣的模塊來負責上面的說的幾大功能。咱們大概有設計三個模塊:第一個模塊是JobManager,主要是提供平臺,供應用方比較方便的配置,能管理任務元數據信息以及其餘的數據倉庫、app信息的管理等。第二個模塊是Scheduler,就是任務的調度中心,負責調度全部的統計任務。第三是任務執行模塊JobExecutor,負責任務從查詢、聚合到最終的結果落地存儲。
接下來詳細介紹下這三個模塊大概的功能點以及實現的方式。先說第一個模塊JobManager,如圖5,主要須要提供一個應用方在這個平臺上去配置他們想要的數據,另一個點是咱們須要有整合數據倉庫,整合數據倉庫主要是爲了業務方可以查看到他相應業務表的信息。右邊這一塊主要是對於元數據統計任務的描述,主要包含這幾個大塊,好比說數據的來源,統計的算子是什麼以及存儲的介質或者特殊場景的數據過濾器、維度聚合以及任務與任務之間的依賴關係描述。這個模塊主要是抽象統計任務,對任務的元數據作統一的配置管理。
第二個比較大的模塊就是任務調度scheduler。當前的實現方式比較簡單,是單點的方式。當前有實現的幾個點,一是可以根據任務的優先級來調度,二是可以根據任務定時的策略進行調度,三是可以調度工做流,就是依賴關係的調度。
第三個模塊是任務執行的模塊JobExecutor(圖6)。根據任務的源信息從插件池裏組裝出具體的query組件,而後到具體的Query層(好比Hive)跑相應的數據,出來後的數據作一些過濾、維度方面的聚合,最終根據任務的信息來組裝數據的存儲層的組件,把統計數據結果寫入到存儲層。
講完三個模塊之後,咱們來回顧一下這個統計平臺的基礎架構。左邊有一個JobManager管理元數據,根據元數據去作統計任務的總體標準流程:查詢、過濾、維度聚合、存儲。有了這樣基礎的框架之後,能夠知足一部分的基礎數據統計的場景,但若是是要支持更多的數據統計的業務場景的話,須要作更多的功能的拓展(圖8)。
這裏面有四個大方向的功能拓展,第一個是針對臨時取數的場景。不必定全部的業務都須要常規例行跑,有很是多的臨時跑數場景,好比分析人員須要臨時看一個相應app的功能數據或者是說運營須要看一個臨時組織活動的數據指標等等,平時會遇到比較多的臨時取數相應的需求。對於解決臨時取數這一塊的需求,咱們作的功能有兩個,一個是有提供直接填寫SQL的功能,支持有SQL基礎的用戶臨時提取數據。這塊是擴展Hive自集成的antlr來作HOL語法解析,解析出來之後,須要校驗HOL的合法性,主要是排除一些相似insert、delete操做,以及限定跑數的時間範圍以避免長時間佔用集羣計算資源。
第二個功能擴展是儘可能豐富數據源,在平時的需求中,會愈來愈多遇到須要導入業務方的MySQL的數據來作簡單的數據統計或者join計算。因此這一塊咱們是有基於sqoop開發一個插件,來支持導入業務MySQL庫表到Hadoop。第三就是Bitmap。這是咱們美圖自研的一套系統,主要是爲了便於多維度去重以及作新增、留存等相應的計算,其原理主要是基於位bit之間的操做。
第三個功能擴展是多存儲,當前大部分的數據是存儲在MongoDB,介於傳統關係型數據庫以及NoSQL之間,既能大部分知足業務的查詢場景,又能保證分佈式的數據存儲。第二就是有臨時比較大的數據導出狀況,業務方須要獲取批量比較大的數據,他們可以導入到HDFS上面,而後業用方從HDFS導出數據用於不一樣的業務應用。第三也支持一些普通文本,好比csv等。第四就是MySQL,這個當前有支持一些分表的策略的存儲。最後一塊就是要豐富統計算子,當前有實現一些去重、數組、TopN等統計算子。
另一個大的功能拓展方面主要是數據可視化(圖9)。由於存儲層是多樣多樣,原來的方式是咱們的存儲層直接暴露給應用的數據後臺,他們從咱們的存儲層查詢數據解析,這個方式有一些不太好的地方,第一個是數據臺若是不去透明化這個存儲層的話,展現層開發須要學習Hbase、MySQL、Mongo等,有比較大的學習成本。第二是數據安全方面的考慮,或者對數據存儲的統一的管理,都是有比較很差的地方,因此後面整了一套統一通用的API,有定製一套統一數據的協議,方便展現層統一對接數據作展現。
但接下來還會有一些問題,咱們須要去考慮平臺化的數據安全(圖10)。好比一般狀況下,美拍的後臺只可以獲取到美拍相關的數據,而不容許美拍後臺能獲取到其餘app商業廣告的數據,因此咱們有實現一個統一的認證中心CA,就是業務方後臺須要先去CA獲取相應的受權token,而後去請求統一通用API時都會帶上acess token,通用API做爲一個通用服務方,會去CA認證這個token是否是合法,合法的話纔會在存儲層查詢相應的數據,最後返回給應用方。
因此到這邊,回顧下美圖統計平臺的總體架構:有一個統一的任務調度中心調度全部的統計任務,而後是JobExecutor負責從插件池來找相應的插件,作一些查詢、過濾等,最終數據存儲到DB,會有一個統一的API封裝存儲層,而後處於一些安全方面考慮有接入CA,最終各個數據後臺對接通用API來作數據展現。
當前正在作的事情以及將來小階段的規劃
當前正在作的事情有兩塊,尚未正式上線或者接入。第一塊是咱們本身開發一套分佈式調度,這套調度主要偏一套通用調度平臺,不只調度統計的任務,後續能夠調度全部的離線計算的任務以及離線統計的任務,接下來全部的統計任務都會遷移到這個通用分佈式調度平臺上作統一的任務調度,替代當前單點的簡單版本的調度中心。後續也會去支持資源方面的隔離和資源方面的調度。第二塊就是數據可視化。咱們剛剛看到的前面那一塊,業務方的全部數據後臺須要一遍遍重複地接入咱們的統一通用API,是有比較多的重複工做,另外一個痛點是確實是涉及到一些比較大的APP,好比美拍他們總體的統計報表很是多,後臺基本上多是成百上千這樣的數據,若是一個數據需求方想看到他們本身的數據,對於他們從成百上千個數據指標去定位到本身的數據指標是很是困難的。數據可視化這麼一個平臺就是解決這樣的問題,我不須要全部的業務方都接入這個通用API,在同一個平臺能夠選擇想要的數據源或者本身可視化的報表,而後呈現本身個性化的數據指標,不須要再去跟全部應用的數據後臺去對接咱們的API,而後作一些圖形方面的展現。因此數據可視化這一塊主要是作統計以及提供定製化、個性化的數據報表,有點相似於網易的bdp或者阿里的dataV等平臺。
另外兩塊是接下來一段時間規劃要作的事情,第一是數據分析人員常常抱怨說這個數據能不能有更快的查詢方式,因此是考慮搭建一個OLAP服務,好比基於kylin等來構建。第二個是實時統計方面,剛剛前面講的要麼是定時的常規的統計需求,要麼就是臨時的統計需求,沒有實時。因此這一塊考慮說後面這個平臺也能對接實時的統計需求,能更快速地對接知足實時統計需求場景。