Elasticsearch 架構原理—— 新資料寫入過程
前言
在分散式日誌服務架構中,我們只需要將logstash的output指向ES就可以了,但是,寫入的資料是如何變成Elasticsearch裡可以被檢索和聚合的索引內容的呢?本文重點介紹資料在寫入Elasticsearch索引流程中發生的具體操作。重點在於其中segment、buffer和translog三部分對實時性和效能方面的影響。
動態更新的Lucene索引
Lucene對於新收到的資料寫入到新的索引檔案裡。Lucene把每次生成的倒排索引,叫做一個segment,然後另外使用一個commit檔案,記錄索引內所有的segment。而生成segment的資料來源則是放在記憶體中的buffer,也就是說,動態更新過程如下:
- 當前索引有3個segment可用;
- 新接收的資料進入記憶體buffer;
- 記憶體buffer刷到磁碟,生成一個新的segment,commit檔案同步更新。
利用磁碟快取實現的準實時檢索
上面的內容中,記憶體buffer刷入磁碟,但是不可避免的問題就是寫磁碟太慢了。對於我們的日誌服務來說,如果要進行一些實時性統計,這個速度是不能接受的。所以,在記憶體buffer刷入磁碟的處理中,還有一箇中間狀態:
- 記憶體buffer生成一個新的segment,刷到檔案系統快取中,Lucene即可檢索這個新的segment。
- 檔案系統快取真正同步到磁碟上,commit檔案更新。
其實就是多加了一步檔案系統快取。Elasticsearch中預設1s中重新整理一次。如果覺得間隔時間還是很短,可以呼叫/_refresh介面來修改。
不過對於日誌場景來說,我們更需要的是更快的寫入效能,所以我們最好是通過/_settings介面或者定製template的方式,加大refresh_intereval引數:
curl -XPOST http://127.0.0.1:9200/logstash-lms-2019.02.19/_settings -d'{"refresh_interval":"10s"}'
如果是匯入歷史資料的場合,甚至可以直接關閉。
索引資料一致性保證——translog提供的磁碟同步控制
refres只是寫到檔案系統快取,如果最後一步寫入到磁碟期間發生了錯誤、硬體故障燈問題,資料會丟失嗎?
這裡有另一個控制機制。Elasticsearch在把資料寫入到記憶體buffer的同時,其實還另外記錄了一個translog日誌。
refres發生時,translog日誌檔案依舊保持原樣。如果期間發生異常,Elasticsearch會從commit位置開始,恢復整個translog檔案中的記錄,保證資料一致性。
等到真正吧segment重新整理到磁碟,commit檔案更新後,translog才會清空,即flush操作。
Elasticsearch預設30分鐘flush一次,或者translog檔案>512M時會主動flush。可以通過以下引數進行設定:
index.translog.flush_threshold_period index.translog.flush_threshold_size #控制每收到多少條資料後flush一次 index.translog.flush_threshold_ops