《攜程機票大數據架構最佳實踐》要點:
本文介紹了攜程機票大數據架構最佳實踐,希望對您有用。如果有疑問,可以聯系我們。
講師介紹
許鵬,攜程機票大數據基礎平臺Leader,負責平臺的構建和運維.深度掌握各種大數據開源產品,如Spark、Presto及Elasticsearch.著有《Apache Spark源碼剖析》一書.
主題簡介:
現如今大數據一塊有很多的開源項目,因此首先搭建平臺的難點其實在于如何選擇一個合適的技術來做整個平臺的架構,第二,因為有業務數據,用了平臺之后的話,如何用平臺把數據分析出來讓用戶有很好的交互性的體驗.第三個層面就是理工科喜歡建模,而在這整個過程當中,我們會形成一種非數據建模,而主要是我們如何分不同層面的人員搭配,進而做成這樣一個大數據團隊.
這個框架應該是一種大路貨,或者更認為是一種比較常見的架構.前面也就是從數據源到消息隊列到數據的清理、數據呈現等這些大家容易想到的東西,而在這樣一個大帽子下面,所不一樣的東西是具體選用什么樣的組件來填這個空,在不同的場景下,每個人的選擇是不大相同的.
像消息隊列這一層,我們選用了Kafka,這是目前大家普遍用到的,因為它有高吞吐量,采用Push和Pull結合的方式,消費端主動拉取數據.ETL這塊,目前大家都希望采用一種可以自定義的方式,一般來說比較流行的是用LinkedIn提供的Camus來做從Kafka到HDFS的數據同步.這應該是一種較為流行的架構.那么放到HDFS上面的數據,基本上是為了批處理做準備的,那么在批處理分析的時候,我們選擇一個什么樣的分析引擎,可能就是一個值得爭議的焦點,也就是說,也許在這個分析引擎的下面,有Hive,有Spark,有Presto,有Impala,還有其它的東西. 在這些引擎當中的選擇或者實踐,需要結合具體使用場景.
下面講講為什么會選擇Presto而不是其它.假設在座的各位有Presto使用經驗的話,會發覺Presto它是一個CLI的用戶界面,并沒有好的一種Web UI,對一般用戶來說,CLI的使用會有難度,不管這是感覺上的還是實際上的,所以需要有個好的Web UI來增加易用性.
當前在GitHub上面能找到的Presto webui的就是Airbnb提供的AirPal,但根據我們的使用經驗,不怎么友好,特別在UTC的時間設置上,同時它的社區維護已停滯在兩年前,這一塊我們做了適配,然后用Presto的StatementClient做了Web UI.前端采用的是jquery的easyui, 像剛才講的批處理這一條線,就是用在了批處理這一塊上.下面這一條線就是說有些數據可能是希望立馬存儲,立即被搜索到,或者做簡要的分析.
作為搜索引擎,社區這一塊,大家耳熟能詳的應該是Elasticsearch,Elasticsearch的社區非常活躍,而且它的推廣速度,應用型上面易都很好.但是Elasticsearch的難點在于如何對它進行好的維護,后面我會講到它可能存在的維護痛點.那么,Elasticsearch有非常強大的搜索能力,響應時間也是非常快的,但是它的用戶接口,有自己的一套基于Lucene的搜索語法,當然Lucene的這一套語法本身是非常極客的,很簡潔,但是一般的人不愿意去學這個東西,因為對于分析師來講去學,就意味著以前的武功,幾十年功夫白費了.
于是我們就采用了一個插件Elastisearch-SQL,這樣就可以采用SQL語句對Elasticsearch進行點查詢或者范圍查詢.而且在Elasticsearch的演進路徑當中,也會支持SQL,按照之前看到的ES roadmap, 應該在17年最遲不超過18年發布6.×,重要的特性之一是對SQL的支持,大家可以看到如果不支持SQL,就等于是自廢武功,或者拒客戶于千里之外.
Web UI是人機交互的部分,我們會進行Ad-hoc查詢,但在整個部門當中有不少程序希望調用查詢,也就是應用的接口,采用SOA的架構,我們自己開發實現了 BigQuery API,可以通過這種調Restful 接口方式,進行取數或者分析.那么我們會自動判別到底是到ES這一側還是到Presto進行取數.
在很多公司的使用當中,數據分析這一塊是需要報表的,就是要有很好的Dashboard.
這個是ETL相對比較細節的一些東西.快速過一下這個圖.在ETL的時間當中,比如說為什么不直接用像Spark或者流的方式,最常見的問題就是小文件的問題,到時候需要清理合并小文件,這很麻煩.如果采用Zeus去調度,然后設定一定數目的Partition,就有一個Map Task對應,盡可能的寫滿一個Block,以64M或者128M為主.在存儲的時候我們除了考慮它的大小之外,存儲格式的選擇也應該是必須考量的范圍.
從我們當前的選擇來看,建議使用ORC這樣的文件格式,采用這個文件格式是由于它已經內嵌了一定級別的索引,盡管索引不是非常細粒度,但是在某些層面是能夠急速地提高檢索,跳過不符合條件的數據塊,避免不必要的數據傳輸.目前相對比較有希望的,或者大力推廣的一個格式就是華為公司在推的CarbonData,它含有的索引粒度,索引信息比ORC更加細致.他們目前也出了1.×的版本,是相對來講較為成熟一個版本.
這里講的是Presto的內部機理.為什么不用Hive和Spark?Hive相當于是俄國的武器,特點就是傻大黑粗,絕對的穩定,穩定到什么程度?穩定到就是它是最慢的一個,有一個笑話就是我的成績一直很穩定,因為老考倒數第一,沒人可以比過,所以一直很穩定,而正數第一不見得很穩定,Hive就是這個特點,絕對可以出來結果,但是會讓你覺得人生沒有指望.
Spark的特點就是它名頭絕對的夠響,但是會發覺Spark具體的使用過程當中有些問題?資源共享是一個問題,如果說你光用Spark,肯定Concurrent Query出現問題的,要前置一個東西,比如Livy或者什么東西來解決掉你的資源共享問題.而且Spark的雄心很大,幾乎想把所有東西都吃下去,所有東西都吃,就很難,因為你要涉及很多的領域.
Presto只專注于數據的分析,只關注SQL查詢層面,只做一件事,這個充分體現了Unix的哲學,遵循只干一件活,不同的活通過Pipeline的方式串起來.而且Presto是基于流水線的,只要有一個塊當中結果出來了,然后比如說我們最典型的就是后面加一個后置的條件,然后limit 10或者Limit 1,你會發覺很快出來結果,用Spark會發現它Where條件的搜索會經歷多個Stage,必須到前面的Stage都完成了才可以跑下一個Stage, 那個Limit 1的結果要到后面才過濾.
從Presto后面給出的這些數據可以看到,這種層面上的一個提升.基于ORC的文件存儲,它的提升應該是5倍或者10倍,10倍到20倍的提升.它的架構簡單來說是有一個Client,然后這個Client提交SQL語句過來,前面有一個Planner和Scheduler,會把相應的SQL的東西分層,分成不同的Stage,每一個Stage有多個Task,這些真正的Task是運行在不同的Workers上面,利用這些Workers去數據源讀取數據.
也就是說Presto是專注于在數據分析這側,具體數據的存儲在外面,這個當中肯定要去解決哪些東西是值得去拉取的,有哪些東西可以直接推到數據源側去搞定,不需要傻乎乎地把很多東西拉上來.
分析引擎比較——Presto與MapReduce
大家可以看到我剛才提到一個基于Stage的方式,一個基于Pipeline的方式,Pipeline的方式就是整個過程中,處理沒有停頓,整個是交叉的,它不會等上一個Stage完成后再進行下一個Stage,Spark的特點就是等到一個Stage結束了,數據吐到Disk中,下一個Stage再去拉數據,然后再進行下一個.Pipeline就是說我有一個Task處理完,直接將數據吐到下一個Task,直到Aggregator節點.
那么在這個過程當中,你也會看到Presto的一個最大特點就在于所有的計算就在內存當中,你會想到人的大腦,機器的內存都是有限的,會崩掉了,崩掉就崩掉了,早死早超生,大不了再跑一趟,這就是Presto的一個基本原則.
MapReduce會重啟,如果成功了還好,重啟很多次崩掉是不是三觀盡毀?通過這種特點也表明Presto適用的場景,適用于交互式查詢,如果是批量的,你晚上要做那種定期報表的話,把整個交給Presto是不負責任的表現,因為有大量的時間,應該給Hive比較好.
下面講講ES層面的東西,也就是近實時的搜索引擎,它所有的東西都是基于Lucene上面進行一個包裹,對JSON支持的非常好.同時Elasticsearch支持橫向、水平擴展,高可用,易于管理,社區很活躍,背后有專門的商業公司.它的競品就是Solr,Solr的Cloud,SolrCloud安裝較為復雜,引入了獨立的第三方東西,對ZooKeeper集群有極大的依賴,這樣使得Solr Cloud的管理變得復雜.
SolrCloud的發展也很活躍,現在是到了6.×,后續就是到7.×,而且SolrCloud的6.×當中引入了對SQL的支持,ES和SolrCloud是同門師兄弟,通過同門師兄弟的相互競爭可以看到發展的趨勢——SQL一定是會支持的.
如果大家做搜索這一塊東西的話,上面這張圖其實是很常見的,它肯定會在某一個節點上面有相應的一個主分區,有一個Primary partition,而在另外一個節點上面它有一個Replicas,而且Replica可能不只一個,如果這些沒有,這張圖就沒有太多好講的.問題是該分幾個Replica,在每臺機器上分幾個不同的partition,如果在從事維護工作的話,上述問題是值得去分析和考究的.
ES調優和運維
下面講ES的調優和運維,從兩個層面出發.
第一個層面就是OS, 講到Linux, 調優過程中自然會考慮到它的文件句柄數,然后它的Memory,它的I/O的調度,I/O的調度線如果在座各位對內核比較感興趣的話,你會發現基本使用CFQ,因為在生產環節上大多會采用Redhat或者CentOS來部署,不會部署到像自己玩的Archlinux或者Gentoo上面,不可能這樣做的.還有就是它的Virtual memory Dirty Ratio,這個東西是會極大地影響響應時間,或者說有時你會發覺I/O操作,而且CPU一直比較高,因為有文件緩存,緩存足夠多的話就一直往磁盤去寫,所以我們的辦法就是把原來設置比較高的vm.dirty_ratio,由默認20%調小到10%.意思就是說緩存內容一旦超過系統內存的10%其它活不要干了,專心致志吐這個緩存內容.?Vm.dirty_background_ratio是說如果達到這個閥值,就開始將文件緩存內容寫入到磁盤.OS層面的調優和數據庫的系統調優有相似性.
另一個層面的調優是ES本身,首先就是說我在一個Cluster上,Shard的數目要均勻分布.
我這里放了一張截圖,這個截圖大家可以看到所有的節點上面,Shard數目上來講是非常均勻的.有相應的參數調整可以達到這樣的效果.第二個就是會有一個Replica的過程,比如新加一臺機器或者說我是減少一臺機器,要做相應的維護,機器的集群會做動態的擴容和縮減.那么這時如果都來做Shard的轉移,整個集群的寫入和查詢會受很大影響,所以做一定的均衡,兩者之間要有一定的Balance.這些講的都是集群級別,下面講索引級別的優化.
索引級別的優化就是我要對Shard的數目,到底是這個Index是分十個Shard存還是5個來存,refresh的頻率,Refresh就是說這個數據寫入多久之后可以被搜索到.Refresh時間拉得越長,數據吞吐量越大,但是可以被搜索到的時間越滯后. 還有Merge的過程,因為分片,為了減少對文件句柄使用, 所以需要進行Merge.有人講就是因為ES支持Schemaless了,所以不需要fixed的Schema.但在實際的使用過程中發覺,如果不做一定限制的話,每個人都認為是自由的,就會出現一個Field的急速膨脹,在某個索引下面成千上萬的字段, 這樣一來索引的寫入速度就下來了.
下圖是我們自己寫的Dashboard,說到ES,可能在座的也有不少在用,如果說你們升級到5.×后發現一點,1.×比較好的插件Marvel,5.×里面就沒有,提供的就是X-pack,X-pack是要收錢的,那么它同時提供了一個所謂的basic版本,Free的東西大家都知道,便宜無好貨,就是說它的功能是對比了1.×的版本,很多信息都是沒有的.
我們的話就是自力更生,因為你所有的內容都是可以通過Rest API讀取到,只不過是需要在前端可視化一下.那么這張圖就是我們做的工作,可以很方便地看到當前節點的寫入量、查詢量,當前節點的索引,Shard數目還有當前集群的狀態,如果一旦狀態變為red,可以郵件通知,在頁面上還可以進一步點下去了解每一個節點和索引的詳細信息.
稍微總結一下,一般來說在調優上考量的不外乎四個維度:一個CPU的維度,一個Memory的角度,還有就是Disk的I/O角度,另外一個是網絡. 比如從原來的百M網卡升級到千M網卡,從千M到萬M,查詢的響應速度會有很大提升.
這是前面提到我們統一的一個SQL查詢的接口,大家可以看到這挺簡陋的,很傻很天真的樣子,我就是上面輸入一個SQL,下面很快就出來一個結果.但就是因為采用了這種方式,因為后面是它采用了Presto這個引擎,在部門內部,我們有不少同事都在使用這個進行數據查詢,目前的日常使用量應該是在近8K的樣子,因為最近還升級了一下網卡,升級到萬M網卡,使得速度更加快.多余的時間喝喝咖啡抽抽煙生活多美好,比等在那里焦慮有意思多了.
在做數據可視化這一塊時,可以借鑒競爭對手或者競品,看看別人在做什么,如果說大家去看Hue, Hue的話,其實就是上面輸入查詢語句之后,后續就把結果很好地顯示出來.我們目前所考慮的就是說如何做到Data visualize的,目前嘗試用Zeppelin,這個可以通過JDBC接口對接Presto,把數據查詢出來,通過簡單的拖拽,直接把報表以圖形化的方式展現出來.
補充一下,Zeppelin這個如果要對接Spark,如果只是一個Spark集群,直接對接這個Spark集群,資源利用率是非常非常低的,但是你在前置一個Livy Server的話,通過Livy來進行資源調度,資源共享會比較好.目前有兩個這一方面的競品,一個Livy,另外一個就是Oyala它提供的Spark Job ServerS,干的活其實都是一樣.Zeppelin是對Livy Server做了整合.
微服務這一塊,我們提供了一個BigQuery API,這樣的好處是有一個統一的查詢入口,有統一的權限管理.因為查詢時不是所有人都應該看到所有的數據,這很容易出問題,可能有比較實實在在的數據,它不像一般的日志數據,特別像機票或者我們這邊的酒店,它的數據有不少的一些敏感信息,這需要做相應的權限管理.這個入口統一之后,做權限管理就比較方便了,出問題的話只要查相應的日志就OK了.而且使用的是統一的查詢語言,都用的是大家比較熟知的這種SQL語句,不是說用了一個新的東西就要學習一套新的知識,這樣子的話原有知識不容易得到傳承,這是大家都應盡量去避免的.
其實在做一套大數據的平臺時,少不了任務調度這一塊.任務調度這一塊我們使用的是Zeus系統,攜程在這一塊開源出來,由我們公司Ops的團隊專門來負責開發和維護個平臺.但是你想,通過這個平臺遞交的任務包括,ETL和定時任務,可以實現將數據從Kafka放入到HDFS或者是把SQL Server和MySQL DB里面的數據同步到HDFS.調度這一塊目前市面上的競品還有AirFlow和其它.
這部分講的是我們團隊的建設.目前我把它分成五個不同的角度,第一個是引擎的開發,這一塊是相對較難的,它對后臺的技術要求比較高.
第二是交互界面設計,整個東西做出來,如果只是做了引擎,或者對引擎做了,但是沒有實際的人用,老板肯定也會叫滾蛋的,肯定要一環套一環,形成有效的傳動,不是單點,只講發動機沒有任何意義的,要講整車.所以有引擎,引擎的要求也比較高,會有一個交互界面的設計,就是我如何用這些引擎的東西.
把這些東西都弄上后,可以轉起來了,整個可以轉起來之后,我們還有個運維,其實大家可以逐步發現一個趨勢,就是無論大數據也好,云平臺也好,對運維的要求都是比較高的,一個好的運維不僅要掌握一個基礎的OS層面的東西,對后臺也得有一個較好的概念或者好的研究.無論是從后臺服務開發轉到運維還是從運維轉后臺服務器開發,兩者都需要去交叉學習.
那么,一個平臺規劃相對來說就是一個架構師或相對更高層一點人員的工作范疇,視野可以更高一點,這樣的角色肩負了架構和產品經理這兩個概念的東西,因為像這種東西最主要是內部使用,比較難以獨立出來.
語言這一塊就是見仁見智,我只是把我們現在采用到的,使用到的東西列了一下,有上述這么多.
大體我們的實踐的就是這些.我們所有的部分應該就在這一張圖里,這張圖的內容看起來比較平淡,但是如果需要把這張圖弄好,確實花了不少時間.
Q1:請問攜程這邊Cluster集群的規模?并發度大概什么情況?因為講的是一天大概八千個,規模和并發度是怎樣的呢?
A1:目前我們的集群規模不是特別大,在十臺左右,但是我們的硬件配置是128G的內存,萬兆網卡,CPU是16核32超線程的.并發的話就是在高峰期我們會有十幾或二十個并發的查詢.
Q2:后面你說是50%的查詢在500,這是什么樣的查詢?
A2:這里的查詢,我們就是要看它查詢的數據、目標數據值,你不可能對所有的數據全值做查詢.如果說你本身就存了10T的數據或者更多的數據,想要一個東西讓它能夠很短的時間都不現實的,不管什么目標都是盡量減少數據的拉取.沒有把SQL貼出來,可能你看到SQL就知道我們怎么存儲數據的.
因為我們有專門的數據分析師團隊,我對他們寫出的SQL佩服得五體投地,他們寫出來的有一千多,我們有同事在,但是那個不能貼出來看.也不是說很傻瓜的SQL,是很強勁的.
有兩種層面,第一個就是我們做了一個從Presto讀取Elasticsearch上的數據,但我們認為還是沒有優化到最好.Elasticsearch-SQL就是說只做了SQL的轉譯,所有真實的計算和分析都在ES上面,這個Elasticsearch-sql是比較流行的一個插件,如果你玩Presto的話, 要找一個讀取Elasticsearch的connector. 那么能找到的就是我們在開發的,已經放在Github上.
(接上問)
Q3:你們還貢獻了Presto對Carbondata讀取的實現,但我們測下來是在拉少量的時候比ORC性能差不多,如果是大量的數據的話carbondata是比ORC差很多.
A3:所以說你看我這張圖,整個的過程沒有.我只能在技術保持熱情,投入多大資源不是我能決定的.
引擎本身上面,我們可能做的并不是一個性能的優化,我們做的就是跟我們內部的數據的對接Carbondata, 可能在性能的提升上面并沒有做很多實際的,到目前為止并沒有很多資源投入,但由于實現了Presto來讀取ESs和Carbondata,我們對presto整個的執行鏈路比較清楚.
(接上問)
Q4:你們目前的版本是?
A4:0.169.
Q5:是京東的嗎?
A5:不是京東的,是Facebook的.
Q6:貴公司每天數據處理的量還有數據團隊的規模是多大?大體的范圍是怎樣的?
A6:要看從哪個層面,如果從業務去,還是日志數據?日志數據我們有一個記錄是每天日增800億.就是一張表.
Q7:如何處理日志數據和銷售數據之間的關系?
A7:這個問題本身是比較大路的問題,你肯定能夠想到的比較簡單或者通用的方式.
Q8:團隊的規模多大?
A8:這個在精不在量,我們的規模在十來個人.
Q9:我想問一下你們Presto連接的ES服務,加載大量的數據比如百萬級別的這種有沒有什么問題?
A9:加載百萬級別的記錄,因為要進行大量I/O操作,會對ES造成比較大的干擾,這也是為什么我們自己后來沒有就是去推Presto ES Connector的原因.舉個最簡單的例子,做個Count操作,也許需要把數據從ES側拉到Presto后再來計算,才能得到這個結果.然而這個東西其實完全可以下推到ES上,直接得到結果返回的.
Q10:這個沒破?
A10:對于OR和AND條件查詢,我們做了下推,聚合側的下推沒有做.
Q11:你用Spark讀取ES也是百萬級的?
A11:需要從里面去讀取,這個很多都是繞不開的,包括用Spark,如果用Elasticsearch-Haoop,就是ES提供的Hadoop組件,會發現也是要用RDD去讀取ES,把數據從ES抽取出來.但是在ES里面,并沒有一個很好的這種所謂的Columnar的Storage,也就是說沒有列存儲,這時候是非常低效的.如果加上一些過濾條件,從ES當中把你所需要的字段抽出來,然后再進行包裝,再通過網絡傳輸,再到達不管Spark還是Presto,這是很低效的.
Q12:寫入大量數據到ES?
A12:寫入大量數據到ES,ES這個還是能夠很好處理的,那個時候牽扯到調優,要考慮到這些因素.從Refresh的時長,replica的數目,merge的緩存大小多個方面進行考量.
文章來自微信公眾號:DBAplus社群