身安不如心安,屋宽不如心宽 。

我对elasticsearch translog flush的理解和疑惑(看完网上的分析后感觉不严谨)

Elasticsearch | 作者 code4j | 发布于2018年03月18日 | 阅读数:8317

网上有的文章介绍过refresh 和 translog的区别,大致就是说refresh是把数据从内存写到系统缓存的过程,这样能确保数据在系统缓存中被检索到;flush把系统缓存提交到磁盘,然后清空translog。
 
然而我今天自己测试了一下发现 flush不仅仅能够做到数据持久化防丢失,同时也实现了refresh的功能,保证数据可以被检索到
而且通过测试结果还发现官网描述的一个前后矛盾的现象,想向大家求教。
 
先说我的测试方法:
 
设置index.refresh_interval 为-1,然后修改一个文档,此时get请求时能看到更新,然后立马search 结果是看不到更新的。refresh后search能够看到了,这印证了第一个说法。

然后我又一次更新了文档,这个时候立马调用flush,发现search也能搜索到了。
 
那么网友们说的预期的结果应该是依然搜不到更新,因为flush仅仅是把系统缓存的数据写到磁盘而已,怎么会把内存buffer的数据同时同步到系统缓存了呢?这不应该是refresh做的事情吗?
 
于是我看了下官方文档。
 官方文档上大概是这样说的:每个写请求都会先写到内存一份数据,然后写translog,这个数据再没有refresh之前是不可见得(除非get请求从translog里面拿),调用refresh后lucene将他从内存写到文件系统缓存,此时就可以被检索到。flush是数据从文件系统缓存到磁盘的过程,重点:
1.Any docs in the in-memory buffer are written to a new segment.
2.The buffer is cleared.
3.A commit point is written to disk.
4.The filesystem cache is flushed with an fsync.
5.The old translog is deleted.
 
第一句话,内存中的文档会被写到心的段,然后后面新的段也就随着commit point提交到磁盘,所以就能被search了。
 
然后官网还有一个flush 配置的描述:durability  这个参数是控制flush策略的,默认是request 就是每个写请求都会触发一个flush。async则是按周期。我看了下2.2的源码,确实是这样。

那么我的问题就是,默认情况下 translog durability 是request,就是每个写请求都会触发flush,这样就和我实验的结果不一致了,也就是说每次index 或者 update 都应该能被search到变化,设置 refresh_interval 在默认的flush策略前应该没有作用才对。  向大佬们求教这个问题
已邀请:

rockybean - Elastic Certified Engineer, ElasticStack Fans,公众号:ElasticTalk

赞同来自: taogger Exrt

refresh flush translog 这三个术语我觉得你有些乱了,这三个过程不是几句话能说明白的,简单说下:
  • refresh 是为了提升实时性存在,segment 不罗盘,但可以及时被搜索;
  • translog 是为了可靠性存在的,将所有未罗盘的写相关操作都落盘记录,和 refresh flush 不相关;
  • flush 是 segment 落盘的操作,在这个操作的同时会触发一次 refresh,落盘后也会把 translog 清空

 
另外 durability 这个参数不是flush 的,是 translog 的,每个 request translog 都罗盘是可靠性最高的配置。
 
明白上面这三项,你的问题应该也就有答案了。translog 只管写自己的持久化文件,这和 flush 不相关
 
其他的问题建议你缕清这三个词的真正意义后再看一遍,应该就没有疑问了

chamcyl

赞同来自: HerbertMahone


那么我的问题就是,默认情况下 translog durability 是request,就是每个写请求都会触发flush


这里的flush是指, 每个写请求会调用fsync ,保证写入到 translog 文件中。
 
------------------------------------------------
我的理解,整个过程是这样的:
一, 大量的写请求过来, 先都放到内存 buffer 中。同时,每个写请求也会写入 translog文件,并调用fsync,保证数据落盘。
 
二, es中的  _refresh 操作,    将 buffer 中数据 弄到一个 segment 文件中 。此时,数据就可以被搜索到了。
但是,并 没有 对segment文件调用 fsync 。
 
三, es中的 _flush 操作, 会先执行一次 refresh操作, 然后调用 fsync让 segment文件落盘 并修改checkpoint 。 此时,translog文件已经没用了 ,删除之。
 
 
 
 

hapjin

赞同来自:

可以参考一下这篇官方博客文章:https://www.elastic.co/cn/blog ... orage
 
In order to accept a document for indexing and make it searchable without requiring a full Lucene commit, Elasticsearch adds it to the Lucene IndexWriter and appends it to the transaction log. After each refresh_interval it will call reopen() on the Lucene indexes, which will make the data searchable without requiring a commit. This is part of the Lucene Near Real Time API. When the IndexWriter eventually commits due to either an automatic flush of the transaction log or due to an explicit flush operation, the previous transaction log is discarded and a new one takes its place.
 
refresh 是为了搜索的可见性。
translog是为了数据可靠性,就像Mysql里面的 redo log,redo log也有redo log buffer,那我想translog也可以buffered吧(没有去看源码)
flush就是 Lucene commit的时候。
 
 

hapjin

赞同来自:

纠结这个问题,又发现一篇文章https://discuss.elastic.co/t/c ... 746/5
  If you open a new IndexReader on this commit all its segments are "searchable"
Now ES uses a feature called NRT (near realtime) that is similar to a commit since it flushes to disc (ES refresh) but doesn't fsync nor does it write a commit point
也许从加粗的注释,能了解下refresh做了什么?

要回复问题请先登录注册