1. 程式人生 > >ElasticSearch注意點

ElasticSearch注意點

文章引用 http://baijiahao.baidu.com/s?id=1582140418694970203&wfr=spider&for=pc

自我Mark下

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

1、OS引數設定

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

這個設定之後還需要在下面加入加入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的只設成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,即便包含巢狀資訊也不會被解析。