好的想法是十分钱一打,真正无价的是能够实现这些想法的人。

一个看似简单的问题,没有搞明白

Elasticsearch | 作者 Charele | 发布于2021年09月29日 | 阅读数:2074

1 新建一个索引,
{
  "settings": {  
    "index.refresh_interval": -1
  }
}
就是禁止它一秒一次的刷新。
 
2 然后put一条文档,
3 然后_flush手动刷新一下(注意不是_refresh)
 
4 然后这个数据用search可以查出来吗?why?
 
 
 
已邀请:

pzw9696

赞同来自: caster_QL

写fileSystem cache: 在lucene层面应该是执行lucene flush操作时候每个文件对应的*Writer|Cosumer有个close操作,以写tmd为例,写文件时候,落在内核缓冲区
截屏2021-10-02_下午2.37_.09_.png


截屏2021-10-02_下午2.40_.16_.png

 
此时还没完全落盘。当然还要经过openifChange 改变IndexSearch持有的SegmentReader才能被搜索到(refresh)。
至于刷磁盘:对应的是Lucene的commit有一次强制的sync

截屏2021-10-02_下午2.41_.53_.png

 

pzw9696

赞同来自: caster_QL

回到题主的问题,以es7.7版本为栗子,单纯的es flush 后面有一个默认参数force=true/false

截屏2021-10-02_下午2.47_.45_.png


 
而flush新版本里面决定是不是附加执行refresh需要满足三个条件之一


截屏2021-10-02_下午2.52_.28_.png


当然这里的refresh操作和之前老版本的refresh操作有什么区别,应该和上面同学发的issue有关
 

Charele - Cisco4321

赞同来自: caster_QL

QQ图片20210930163054.png

 
关于上面那个问题,有兴趣的可以做一个测试。
1 用lucene写一条数据,
flush()后用Runtime.getRuntime().halt(0)退出
 
2 用lucene写一条数据,
commit()后用Runtime.getRuntime().halt(0)退出 
其实两个操作在数据文件方面是一模一样的。
唯一的不同点在红处。 
我想说的是,flush()就是实实在在的写硬盘!
耳不是“落在内核缓冲区”,也不是“写fileSystem cache”
 
(lucene的flush()可以简单的理解为ES里的_refresh)

pzw9696

赞同来自: caster_QL

@Charele  你说的没错,flush 是在写磁盘,但是flush 因为I/O缓冲机制,程序在运行时,并不会马上持久化到磁盘上,而commit一定是等它同步完。也就是说数据还是会有丢失的风险。具体你对比下执行完flush 和 commit操作 然后死循环一段时间,观察下形成的文件在磁盘出现的时间点就知道了,你会发现commit执行完会马上出现,而flush要等一会。

caster_QL

赞同来自:

搜索不出来。
从 index-buffer 中取数据到 fileSystem cache 中的过程叫做 refresh。
从 fileSystem cache 写入磁盘的过程就是 flush。
可以参考下图流程。
 

caster_QL

赞同来自:

6版本 flush 时会进行 refresh 操作,7版本移除了,参考6 7 版本代码对比如下图。
另外还请大佬指教上图有什么荒唐之处,来源于网络,我没看出有什么毛病。。。

Charele - Cisco4321

赞同来自:

QQ图片20210930163054.png

 
7.x中也是会进行refresh的,
只不过它放在了getEngine().flush(force, waitIfOngoing)这个方法里面。

Charele - Cisco4321

赞同来自:

谈谈我为什么说那个图荒唐。
 
楼上大佬说了是filesytem cache的问题,不过我的怀疑出发点不同
 
我在别的地方也看见过如此理论:
说refresh是把数据写到了filesytem cache里面,所以就可以search到了。 
先不谈它是不是这样做的:“写到了filesytem cache“,
 
一个前提的问题是:Java中哪个代码,哪个方法是写filesytem cache的???你见过吗?
(不管是lucene,还是es,它总是通过java来执行的)

要回复问题请先登录注册