1. 程式人生 > >乾貨 | 攜程機票大資料架構最佳實踐

乾貨 | 攜程機票大資料架構最佳實踐

本文轉載自 攜程技術中心(ctriptech) 公眾號,本文PPT請點選下面 閱讀原文 獲取 

作者簡介

 

許鵬,攜程機票大資料基礎平臺Leader,負責平臺的構建和運維。深度掌握各種大資料開源產品,如Spark、Presto及Elasticsearch。著有《Apache Spark原始碼剖析》一書。本文來自許鵬在〖DAMS 2017中國資料資產管理峰會〗上的分享,首發DBAplus社群(ID:dbaplus)。

現如今大資料一塊有很多的開源專案,因此首先搭建平臺的難點其實在於如何選擇一個合適的技術來做整個平臺的架構,第二,因為有業務資料,用了平臺之後的話,如何用平臺把資料分析出來讓使用者有很好的互動性的體驗。第三個層面就是理工科喜歡建模,而在這整個過程當中,我們會形成一種非資料建模,而主要是我們如何分不同層面的人員搭配,進而做成這樣一個大資料團隊。

一、資料平臺技術選型

1、整體框架

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1

這個框架應該是一種大路貨,或者更認為是一種比較常見的架構。前面也就是從資料來源到訊息佇列到資料的清理、資料呈現等這些大家容易想到的東西,而在這樣一個大帽子下面,所不一樣的東西是具體選用什麼樣的元件來填這個空,在不同的場景下,每個人的選擇是不大相同的。

像訊息佇列這一層,我們選用了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,就等於是自廢武功,或者拒客戶於千里之外。 

WebUI是人機互動的部分,我們會進行Ad-hoc查詢,但在整個部門當中有不少程式希望呼叫查詢,也就是應用的介面,採用SOA的架構,我們自己開發實現了 BigQuery API,可以通過這種調Restful 介面方式,進行取數或者分析。那麼我們會自動判別到底是到ES這一側還是到Presto進行取數。

在很多公司的使用當中,資料分析這一塊是需要報表的,就是要有很好的Dashboard。

2、ETLPipeLine -- Gobblin

640?wx_fmt=jpeg

這個是ETL相對比較細節的一些東西。快速過一下這個圖。在ETL的時間當中,比如說為什麼不直接用像Spark或者流的方式,最常見的問題就是小檔案的問題,到時候需要清理合並小檔案,這很麻煩。如果採用Zeus去排程,然後設定一定數目的Partition,就有一個Map Task對應,儘可能的寫滿一個Block,以64M或者128M為主。在儲存的時候我們除了考慮它的大小之外,儲存格式的選擇也應該是必須考量的範圍。

從我們當前的選擇來看,建議使用ORC這樣的檔案格式,採用這個檔案格式是由於它已經內嵌了一定級別的索引,儘管索引不是非常細粒度,但是在某些層面是能夠急速地提高檢索,跳過不符合條件的資料塊,避免不必要的資料傳輸。目前相對比較有希望的,或者大力推廣的一個格式就是華為公司在推的CarbonData,它含有的索引粒度,索引資訊比ORC更加細緻。他們目前也出了1.×的版本,是相對來講較為成熟一個版本。

3、分析引擎 -Presto

640?wx_fmt=jpeg

這裡講的是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的結果要到後面才過濾。

640?wx_fmt=jpeg

640?wx_fmt=jpeg

從Presto後面給出的這些資料可以看到,這種層面上的一個提升。基於ORC的檔案儲存,它的提升應該是5倍或者10倍,10倍到20倍的提升。它的架構簡單來說是有一個Client,然後這個Client提交SQL語句過來,前面有一個Planner和Scheduler,會把相應的SQL的東西分層,分成不同的Stage,每一個Stage有多個Task,這些真正的Task是執行在不同的Workers上面,利用這些Workers去資料來源讀取資料。

也就是說Presto是專注於在資料分析這側,具體資料的儲存在外面,這個當中肯定要去解決哪些東西是值得去拉取的,有哪些東西可以直接推到資料來源側去搞定,不需要傻乎乎地把很多東西拉上來。

分析引擎比較——Presto與MapReduce

640?wx_fmt=jpeg

大家可以看到我剛才提到一個基於Stage的方式,一個基於Pipeline的方式,Pipeline的方式就是整個過程中,處理沒有停頓,整個是交叉的,它不會等上一個Stage完成後再進行下一個Stage,Spark的特點就是等到一個Stage結束了,資料吐到Disk中,下一個Stage再去拉資料,然後再進行下一個。Pipeline就是說我有一個Task處理完,直接將資料吐到下一個Task,直到Aggregator節點。

那麼在這個過程當中,你也會看到Presto的一個最大特點就在於所有的計算就在記憶體當中,你會想到人的大腦,機器的記憶體都是有限的,會崩掉了,崩掉就崩掉了,早死早超生,大不了再跑一趟,這就是Presto的一個基本原則。

MapReduce會重啟,如果成功了還好,重啟很多次崩掉是不是三觀盡毀?通過這種特點也表明Presto適用的場景,適用於互動式查詢,如果是批量的,你晚上要做那種定期報表的話,把整個交給Presto是不負責任的表現,因為有大量的時間,應該給Hive比較好。

4、近實時搜尋 –Elasticsearch

下面講講ES層面的東西,也就是近實時的搜尋引擎,它所有的東西都是基於Lucene上面進行一個包裹,對JSON支援的非常好。同時Elasticsearch支援橫向、水平擴充套件,高可用,易於管理,社群很活躍,背後有專門的商業公司。它的競品就是Solr,Solr的Cloud,SolrCloud安裝較為複雜,引入了獨立的第三方東西,對ZooKeeper叢集有極大的依賴,這樣使得Solr Cloud的管理變得複雜。

SolrCloud的發展也很活躍,現在是到了6.×,後續就是到7.×,而且SolrCloud的6.×當中引入了對SQL的支援,ES和SolrCloud是同門師兄弟,通過同門師兄弟的相互競爭可以看到發展的趨勢——SQL一定是會支援的。

640?wx_fmt=jpeg

如果大家做搜尋這一塊東西的話,上面這張圖其實是很常見的,它肯定會在某一個節點上面有相應的一個主分割槽,有一個Primary partition,而在另外一個節點上面它有一個Replicas,而且Replica可能不只一個,如果這些沒有,這張圖就沒有太多好講的。問題是該分幾個Replica,在每臺機器上分幾個不同的partition,如果在從事維護工作的話,上述問題是值得去分析和考究的。

ES調優和運維

640?wx_fmt=jpeg

下面講ES的調優和運維,從兩個層面出發。

第一個層面就是OS, 講到Linux, 調優過程中自然會考慮到它的檔案控制代碼數,然後它的Memory,它的I/O的排程,I/O的排程線如果在座各位對核心比較感興趣的話,你會發現基本使用CFQ,因為在生產環節上大多會採用Redhat或者CentOS來部署,不會部署到像自己玩的Archlinux或者Gentoo上面,不可能這樣做的。

還有就是它的Virtual memory DirtyRatio,這個東西是會極大地影響響應時間,或者說有時你會發覺I/O操作,而且CPU一直比較高,因為有檔案快取,快取足夠多的話就一直往磁碟去寫,所以我們的辦法就是把原來設定比較高的vm.dirty_ratio,由預設20%調小到10%。意思就是說快取內容一旦超過系統記憶體的10%其它活不要乾了,專心致志吐這個快取內容。 Vm.dirty_background_ratio是說如果達到這個閥值,就開始將檔案快取內容寫入到磁碟。OS層面的調優和資料庫的系統調優有相似性。

另一個層面的調優是ES本身,首先就是說我在一個Cluster上,Shard的數目要均勻分佈。

640?wx_fmt=jpeg

我這裡放了一張截圖,這個截圖大家可以看到所有的節點上面,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.×的版本,很多資訊都是沒有的。

640?wx_fmt=jpeg

我們的話就是自力更生,因為你所有的內容都是可以通過Rest API讀取到,只不過是需要在前端視覺化一下。那麼這張圖就是我們做的工作,可以很方便地看到當前節點的寫入量、查詢量,當前節點的索引,Shard數目還有當前叢集的狀態,如果一旦狀態變為red,可以郵件通知,在頁面上還可以進一步點下去了解每一個節點和索引的詳細資訊。

640?wx_fmt=jpeg

稍微總結一下,一般來說在調優上考量的不外乎四個維度:一個CPU的維度,一個Memory的角度,還有就是Disk的I/O角度,另外一個是網路。 比如從原來的百M網絡卡升級到千M網絡卡,從千M到萬M,查詢的響應速度會有很大提升。

640?wx_fmt=jpeg

這是前面提到我們統一的一個SQL查詢的介面,大家可以看到這挺簡陋的,很傻很天真的樣子,我就是上面輸入一個SQL,下面很快就出來一個結果。但就是因為採用了這種方式,因為後面是它採用了Presto這個引擎,在部門內部,我們有不少同事都在使用這個進行資料查詢,目前的日常使用量應該是在近8K的樣子,因為最近還升級了一下網絡卡,升級到萬M網絡卡,使得速度更加快。多餘的時間喝喝咖啡抽抽菸生活多美好,比等在那裡焦慮有意思多了。

5、資料視覺化——Zeppelin

640?wx_fmt=jpeg

640?wx_fmt=jpeg

在做資料視覺化這一塊時,可以借鑑競爭對手或者競品,看看別人在做什麼,如果說大家去看Hue, Hue的話,其實就是上面輸入查詢語句之後,後續就把結果很好地顯示出來。我們目前所考慮的就是說如何做到Data visualize的,目前嘗試用Zeppelin,這個可以通過JDBC介面對接Presto,把資料查詢出來,通過簡單的拖拽,直接把報表以圖形化的方式展現出來。

補充一下,Zeppelin這個如果要對接Spark,如果只是一個Spark叢集,直接對接這個Spark叢集,資源利用率是非常非常低的,但是你在前置一個Livy Server的話,通過Livy來進行資源排程,資源共享會比較好。目前有兩個這一方面的競品,一個Livy,另外一個就是Oyala它提供的SparkJob ServerS,乾的活其實都是一樣。Zeppelin是對Livy Server做了整合。

6、資料微服務 –Rest查詢介面

640?wx_fmt=jpeg

微服務這一塊,我們提供了一個BigQuery API,這樣的好處是有一個統一的查詢入口,有統一的許可權管理。因為查詢時不是所有人都應該看到所有的資料,這很容易出問題,可能有比較實實在在的資料,它不像一般的日誌資料,特別像機票或者我們這邊的酒店,它的資料有不少的一些敏感資訊,這需要做相應的許可權管理。

這個入口統一之後,做許可權管理就比較方便了,出問題的話只要查相應的日誌就OK了。而且使用的是統一的查詢語言,都用的是大家比較熟知的這種SQL語句,不是說用了一個新的東西就要學習一套新的知識,這樣子的話原有知識不容易得到傳承,這是大家都應儘量去避免的。

7、任務排程器 –Job Scheduler

  • Zeus-https://github.com/ctripcorp/dataworks-zeus

640?wx_fmt=jpeg

其實在做一套大資料的平臺時,少不了任務排程這一塊。任務排程這一塊我們使用的是Zeus系統,攜程在這一塊開源出來,由我們公司Ops的團隊專門來負責開發和維護個平臺。但是你想,通過這個平臺遞交的任務包括,ETL和定時任務,可以實現將資料從Kafka放入到HDFS或者是把SQL Server和MySQLDB裡面的資料同步到HDFS。排程這一塊目前市面上的競品還有AirFlow和其它。

二、資料團隊能力建設

640?wx_fmt=jpeg

這部分講的是我們團隊的建設。目前我把它分成五個不同的角度,第一個是引擎的開發,這一塊是相對較難的,它對後臺的技術要求比較高。

第二是互動介面設計,整個東西做出來,如果只是做了引擎,或者對引擎做了,但是沒有實際的人用,老闆肯定也會叫滾蛋的,肯定要一環套一環,形成有效的傳動,不是單點,只講發動機沒有任何意義的,要講整車。所以有引擎,引擎的要求也比較高,會有一個互動介面的設計,就是我如何用這些引擎的東西。

把這些東西都弄上後,可以轉起來了,整個可以轉起來之後,我們還有個運維,其實大家可以逐步發現一個趨勢,就是無論大資料也好,雲平臺也好,對運維的要求都是比較高的,一個好的運維不僅要掌握一個基礎的OS層面的東西,對後臺也得有一個較好的概念或者好的研究。無論是從後臺服務開發轉到運維還是從運維轉後臺伺服器開發,兩者都需要去交叉學習。

那麼,一個平臺規劃相對來說就是一個架構師或相對更高層一點人員的工作範疇,視野可以更高一點,這樣的角色肩負了架構和產品經理這兩個概念的東西,因為像這種東西最主要是內部使用,比較難以獨立出來。

語言這一塊就是見仁見智,我只是把我們現在採用到的,使用到的東西列了一下,有上述這麼多。

大體我們的實踐的就是這些。我們所有的部分應該就在這一張圖裡,這張圖的內容看起來比較平淡,但是如果需要把這張圖弄好,確實花了不少時間。

640?wx_fmt=jpeg