Elasticsearch translog文件介紹


這篇文章主要介紹Elasticsearch的索引工作機制,它是如何利用translog來保證數據的安全,以及我們在生產環境中如何優化translog的參數來最大化性能,主要會介紹到elastic中常見的2個操作:refresh和flush,以及這2個接口是如何保證數據能夠被檢索到的。

數據持久化

我們把數據寫到磁盤后,還要調用fsync才能把數據刷到磁盤中,如果不這樣做在系統掉電的時候就會導致數據丟失,這個原理相信大家都清楚,elasticsearch為了高可靠性必須把所有的修改持久化到磁盤中。

elastic底層采用的是lucene這個庫來實現倒排索引的功能,在lucene的概念里每一條記錄稱為document(文檔),lucene使用segment(分段)來存儲數據,用commit point來記錄所有segment的元數據,一條記錄要被搜索到,必須寫入到segment中,這一點非常重要,后面會介紹為什么elastic搜索是near-realtime(接近實時的)而不是實時的。

elastic使用translog來記錄所有的操作,我們稱之為write-ahead-log,我們新增了一條記錄時,es會把數據寫到translog和in-memory buffer(內存緩存區)中,如下圖所示:

內存緩存區和translog就是near-realtime的關鍵所在,前面我們講過新增的索引必須寫入到segment后才能被搜索到,因此我們把數據寫入到內存緩沖區之后並不能被搜索到,如果希望該文檔能立刻被搜索,需要手動調用refresh操作。

refresh操作

默認情況下,es每隔一秒鍾執行一次refresh,可以通過參數index.refresh_interval來修改這個刷新間隔,執行refresh操作具體做了哪些事情呢?

  • 所有在內存緩沖區中的文檔被寫入到一個新的segment中,但是沒有調用fsync,因此內存中的數據可能丟失
  • segment被打開使得里面的文檔能夠被搜索到
  • 清空內存緩沖區

執行refresh后的狀態如下圖所示:

refresh的開銷比較大,我在自己環境上測試10W條記錄的場景下refresh一次大概要14ms,因此在批量構建索引時可以把refresh間隔設置成-1來臨時關閉refresh,等到索引都提交完成之后再打開refresh,可以通過如下接口修改這個參數:

 

1
2
3
4
5
curl -XPUT 'localhost:9200/test/_settings' -d '{
"index" : {
"refresh_interval" : "-1"
}
}'

 

 

 

 

另外當你在做批量索引時,可以考慮把副本數設置成0,因為document從主分片(primary shard)復制到從分片(replica shard)時,從分片也要執行相同的分析、索引和合並過程,這樣的開銷比較大,你可以在構建索引之后再開啟副本,這樣只需要把數據從主分片拷貝到從分片:

1
2
3
4
5
curl -XPUT 'localhost:9200/my_index/_settings' -d ' {
"index" : {
"number_of_replicas" : 0
}
}'

 

 

 

 

執行完批量索引之后,把刷新間隔改回來:

1
2
3
4
5
curl -XPUT 'localhost:9200/my_index/_settings' -d '{
"index" : {
"refresh_interval" : "1s"
}
}'

 

 

 

 

你還可以強制執行一次refresh以及索引分段的合並:

1
2
curl -XPOST 'localhost:9200/my_index/_refresh'
curl -XPOST 'localhost:9200/my_index/_forcemerge?max_num_segments=5'

 

 

flush操作

隨着translog文件越來越大時要考慮把內存中的數據刷新到磁盤中,這個過程稱為flush,flush過程主要做了如下操作:

  • 把所有在內存緩沖區中的文檔寫入到一個新的segment中
  • 清空內存緩沖區
  • 往磁盤里寫入commit point信息
  • 文件系統的page cache(segments) fsync到磁盤
  • 刪除舊的translog文件,因此此時內存中的segments已經寫入到磁盤中,就不需要translog來保障數據安全了

flush之后的狀態如下所示:

es有幾個條件來決定是否flush到磁盤,不同版本的es參數有所不同,大家可以參考es對應版本的文檔來查看這幾個參數:es translog,這里介紹下1.7版本的flush參數:

  • index.translog.flush_threshold_ops,執行多少次操作后執行一次flush,默認無限制
  • index.translog.flush_threshold_size,translog的大小超過這個參數后flush,默認512mb
  • index.translog.flush_threshold_period,多長時間強制flush一次,默認30m
  • index.translog.interval,es多久去檢測一次translog是否滿足flush條件

上面的參數是es多久執行一次flush操作,在系統恢復過程中es會比較translog和segments中的數據來保證數據的完整性,為了數據安全es默認每隔5秒鍾會把translog刷新(fsync)到磁盤中,也就是說系統掉電的情況下es最多會丟失5秒鍾的數據,如果你對數據安全比較敏感,可以把這個間隔減小或者改為每次請求之后都把translog fsync到磁盤,但是會占用更多資源;這個間隔是通過下面2個參數來控制的:

  • index.translog.sync_interval 控制translog多久fsync到磁盤,最小為100ms
  • index.translog.durability translog是每5秒鍾刷新一次還是每次請求都fsync,這個參數有2個取值:request(每次請求都執行fsync,es要等translog fsync到磁盤后才會返回成功)和async(默認值,translog每隔5秒鍾fsync一次)

讀者需要弄清楚flush和fsync的區別,flush是把內存中的數據(包括translog和segments)都刷到磁盤,而fsync只是把translog刷新的磁盤(確保數據不丟失)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM