1. 程式人生 > >攜程機票ElasticSearch叢集運維馴服記

攜程機票ElasticSearch叢集運維馴服記

講師介紹

許鵬,攜程機票大資料基礎平臺Leader,負責平臺的構建和運維。深度掌握各種大資料開源產品,如Spark、Presto及Elasticsearch。著有《Apache Spark原始碼剖析》一書。

今天跟大家分享的是攜程機票ElasticSearch叢集的規劃和具體設定,內容相對細緻,同時也會涉及到叢集的監控分享。

一、整體架構

為什麼採用ES作為搜尋引擎呢?在做任何事情的時候,不要一上來就急著瞭解怎麼做這件事情,而是去想想這件事情為什麼值得去做。

資料

這個是比較通用的資料的流程,一般會通過Kafka分離產生資料的應用程式和後面的平臺,通過ETL落到不同的地方,按照優先順序和冷熱程度採取不同的儲存方式。一般來說,冷資料存放到HDFS,如果溫資料、或者熱資料會採用Database以及Cache,目前分散式Cache還沒有明顯的強者出現,這將會成為未來的一個競爭點。

一旦資料落地,我們會做兩方面的應用,第一個方面的應用是傳統BI,比如會產生各種各樣的報表,報表的受眾是更高的決策層和管理層,他們看了之後,會有相應的業務調整和更高層面的規劃或轉變。這個使用路徑比較傳統的,在資料倉庫時代就已經存在了。現在有一種新興的場景就是利用大資料進行快速決策,資料不是餵給人的,資料分析結果由程式來消費,其實是再次的反饋到資料來源頭即應用程式中,讓他們基於快速分析後的結果,調整已有策略,這樣就形成了一個數據使用的迴圈。

這樣我們從它的輸入到輸出會形成一種閉環,而且這個閉環全部是機器參與的,這也是為什麼去研究這種大規模的,或者快速決策的原因所在。如果資料最終還會給人本身來看的話,就沒有必要更新那麼快,因為一秒鐘重新整理一次或者10秒鐘重新整理一次對人是沒有意義的,因為我們腦子不可能一直轉那麼快,基於資料一直的做調整也是不現實的,但是對機器來講,就完全沒有問題。

二、叢集規劃

資料

這是大體上的一個規劃,當然,從左到右有一個結點,這個節點本身不存在資料的,你可以簡單地認為它只是負責查詢的入口。第二層用來承載具體的資料,然後這些資料的搜尋本身會發生在這裡。最後一層是MASTER的節點,主要是管理元資料,元資料包含有叢集中的機器資訊,以及寫入到我的資料節點上的這些索引設定資訊、索引Schema都是由Master管理。

我這裡是以ES5.X版本為依據的,大家看ES文件,我這上面有一個節點沒有寫,就是沒有寫它的Ingest節點,它可以在資料真正寫入到Index之前做一些轉換。

三、叢集配置

下面要講的設定就非常具體了,從三個層面來講:第一個有關Linux的系統配置,第二是叢集層面的引數設定,最後會涉及到儲存到叢集上的索引設定。

1、OS引數設定

像OS這個引數設定,首先提到的是記憶體相關的引數,由於ES採用Mapping機制,將檔案對映到記憶體,在系統級別有一些相關的引數要設定。另一個就是檔案數,假設我們所有都設定到最大65535。

OS引數

這個設定之後還需要在下面加入加入login這個檔案,這裡講得非常具體,可以說是一個教程。

這裡我只是做了一個示例,在Ext4檔案系統中,每一次訪問一個檔案或者目錄時,其實OS級別會記錄訪問時間,如果只是在海量檔案的情況,上述的記錄資訊就會對IO有影響。有一篇文章提到,關閉檔案訪問時間資訊之後,系統IO效能可以提升20%—30%。

我們知道Linux裡面檔案資訊,不是直接改一次之後就寫入到磁碟,它會先有一個檔案的快取,檔案的快取什麼情況下會被寫入到disk裡面?有兩個相應的系統引數可以設定的,一個是vm.dirty_background_ratio,一個是vm.dirty_ratio,一旦快取佔據記憶體超過百分比(預設值是20%)之後,核心就停止其它方面的操作,而只做檔案的快取吐到disk的操作,這時效果有點像Java裡進行垃圾回收一樣,對外界停止響應。 vm.dirty_ratio就是當它快取量達到20%時,它就其它的什麼都不幹了,只做資料同步到disk一件。

記憶體不夠時,會使用swap空間, 記憶體很大的話,可以不用建立swap空間。預設值是60,但是我們把它設定為零的話,是跟swap off效果一樣。但為了避免核心出現OOM, 只是將其設定為1。

2、ElasticSearch引數設定

剛才兩個講的都是系統級別的設定,一個是記憶體,另一個是系統級別的IO,下面講的是針對ES—JVM的設定。

ElasticSearch引數設定

這裡建議,不管實體記憶體有多大,分配給Elasticsearch的只設成32G,同時後面如果出現OOM,程序直接退出。

為什麼說要把它改成這個呢?因為我們在使用一個叢集時看到,有時因為聚合操作的原因,會導致某一臺機器上的JAVA程序出現OOM,但是這個JVM程序還在,並沒有退出,退出的話可以通過monit捕捉到,也可以進行重啟。如果沒有退出,而是一直掛在那的話,就不能提供正常的服務。 此外加上這個引數的話,需要升級一下JDK版本,JDK要求1.8.0_92, 從這個版本開始支援ExitOnOutOfMemoryError引數。

另外一種辦法就是如果我們記憶體不能升級JDK、存在種種現實約束的話,可以在這個時候用另一種方式來實現,在JVM啟動引數中加入

-XX:OnOutOfMemoryError=”kill -9 %p”。

引數設定

這裡就是講輸入到ElasticSearch裡面每個叢集的一些引數,一些相對比較主要的一些引數。這裡的引數配了一幅圖,這幅圖最想表明的意思是說,我的引數的配置要使得我從整個叢集的角度上來看,它每一臺機器上的shard數目基本是相當的。

這裡有一點,引數設定能保證shard數目是基本相當的,但並不是保證每一個shard的大小相等,這兩者還是有差異的。決定每個叢集上shard相等的引數是由這個balance決定,它預設一個是0.5,把它往下調的話,就不可以傾斜;往上調的話對傾斜的容忍度相對比較高。

ElasticSearch是一個高可靠的系統,叢集的一個節點掛掉了,另一個節點是可以繼續的。掛掉的節點是進行恢復,為了避免恢復工作對叢集造成太多影響,主要是避免大的I/O消耗,需要進行引數設定。比如叢集中同時在進行恢復的索引可以是多少個,還有就是一個node上能允許shard在做恢復。 這兩個引數是cluster_concurrent_rebalance和node_concurrent_recoveries。

如果要縮容、對某一臺機器進行維護、將其從叢集中拉出來該怎麼辦?這個時候可以設定exclude名單,名單可以通過ip地址或主機名來指定。一旦設定的exlude名單,該名單上節點中的索引資料被拉到別的機器上面,資料被拉完之後,就可以被這個叢集拉出去的機器進行維護,避免維護帶來的資料丟失。

3、索引引數設定

索引引數

這是具體到一個索引引數的設定。在講具體引數之前,我們可以先講一下ElasticSearch索引引數的設定、輸入以及中間發生的過程。當真正的資料請求到達ElasticSearch節點之後,它一方面會寫入到記憶體中,另外一部分會寫入到TransactionLog。

寫入到記憶體並不意味著可以被搜尋,要通過Refresh操作,才可以被搜尋到。Refresh之後,資料可以被搜尋到,此刻資料還在記憶體中,如果很不巧的話,在這個時候斷電,或者出現其它故障不可用了,那麼等到這臺機器再恢復時,我剛才寫的內容就丟失掉了, 因為並沒有被持久化到磁碟。 為了持久化這個內容,需要進行一次FLUSH操作, flush的內容會被寫到一個segment中。 可想而知,隨著時間的推移,系統會產生大量的segments,這些segment需要把它合併成一個大的。不合併成一個大的會怎樣呢?不合併成一個大的,就是說每一個segment都會吃掉一些檔案控制代碼,檔案控制代碼數是有限的。另一個帶來的就是查詢效能下降,因為查詢的時候,要對所有segments進行訪問,效率就比較低了。

有了剛才講的三步之後,再來看下面的引數就比較容易好理解了。 Refresh_interval 過多久可以讓你查詢到,時間越短就可以被越快地檢索到,但是意味著我相應的I/O也上去了,在有大批量資料匯入時,這個數值會適當的調大。

在我們目前部署的叢集中,高峰時候每秒寫入量,有十幾萬。 為了應對這種場景,將refresh_interval設定為100多秒或者90秒以上。

Number_of_shards索引分片的數目,這個數目可以設定得大一些,還有每一個分片的副本,在大批量匯入時,由於副本數目是可以動態調整的,副本數也可以先設定為零,等資料全部匯入後,再設定為非0值。 副本數可以動態調整,但是分片數目是無法動態調整的,也就是說,除非重建另外一個索引,不然原先設定的是啥樣就只能啥樣。 這個FLUSH也可以調大,需要的時候可以設定得大一些。

下面就是做segments合併的執行緒數,如果是spin disk的話,就使用預設值1,如果是SSD的話,可以把它調大一些。 講到SSD程式碼的話, 為了進一步優化效能,可以將系統的i/o scheduler設定為noop 。

索引

這裡是針對每個Index的Schema設定。假設事先並不能確定索引,大部分我們可以採用動態的template。 上述的動態模板表示的是, 如果字串小於10915, 就採用keyword來儲存。

下面一欄對應特別特別大的欄位,如果我們只是儲存這個欄位的內容,不對這個欄位做搜尋也不做任何分詞,可以將型別設定為object,enabled設定為false,即便包含巢狀資訊也不會被解析。

前面講的是一些設定方面的內容,下面講如何放開這個ElasticSearch的使用。想法跟大的原則一樣,儘量避免開發人員直接呼叫Elasticsearch的API來操作ElasticSearch,因為這樣產生的問題不容易控制,畢竟每個人對ElasticSearch的熟悉程度不一樣。 建議先統一入口,在包裹之後的API對ES進行操作。 利用BigQuery API對寫入到Elasticserch的資料進行查詢,開發人員直接寫SQL語句。如果SQL語句本身有問題的話,在Elasticsearch-SQL一側就可以將其擋掉。

四、叢集監控

1、監控內容

監控

維護一個叢集的話,肯定離不開對叢集的監控。監控的內容,大體上來說分成OS層面還有ES索引層面的內容。

OS層面就是記憶體、CPU,索引層面就是分片還有它的Field  Data以及其它佔用的記憶體數。索引的話就是每個索引數設定得合理,這些分片數設定得合理與否,分片是否在每個叢集裡比較均勻地分佈;針對每一個索引的話,它的查詢量是不是過大,如果過大的話,那麼整個叢集也會有問題。ElasticSearch並不是一個能夠很好地支援高併發查詢的系統。每一個索引中包含的欄位數不能過多。

2、監控工具

監控工具

監控工具是eyeones,是我們自己寫的一個工具, Elasticsearch 5.x中提供的x-pack基本版與elasticsearch 1.x中提供的marvel相比,精簡掉了好多有用的資訊,這是我們為什麼自己寫一個監控面板的原因。

監控

從這裡你可以看到這是針對節點的負載情況,然後它的記憶體使用情況,還有就是我這上面所承載的索引數目、每個節點上的查詢數、分片落了多少。

這是一個針對索引內容更加明細的量化指標,上面是索引的情況,點選任意一個具體的索引,都會有相關內容。

這個的話我們是把它放到Github,如果大家有興趣可以在上面繼續改造。

原文來自微信公眾號:DBAplus社群