Lucene采用了这种方案,
- 它构建的单个倒排索引称为segment,合在一起称为Index,
- 与ES中的Index概念不同。
- ES中的一个Shard对应一个Lucene Index。
segment写入磁盘的过程依然很耗时,
- 可以借助文件系统缓存的特性,
- 先将segment在缓存中 IT创建并开放查询来进一步提升实时性,
- 该过程在es中被称为refresh。
- 在refresh之前文档会先存储在一个buffer中,
- refresh时将buffer中的所有文档清空并生成segmentes
- 默认每1秒执行一次refresh,
- 因此文档的实时性被提高到1秒,
- 这也是es被称为近实时(Near Real Time)的真正原因
如果在内存中的segment还没有写入磁盘前发生了宕机,那么内存中的文档就无法恢复了。
- 那么如何解决这个问题呢?
- es引入translog机制。写入文档到buffer时,同时将该操作写入translog。
- translog 文件会即时写入磁盘(fsync),6.x默认每个请求都会落盘,
- 可以修改为每5秒写一次,这样风险便是丢失5秒内的数据,相关配置为index.translog.*
- es重新启动时会自动检查translog文件,并从中恢复数据
flush负责将内存中的segment写入磁盘,主要做如下的工作:
- 将translog写入磁盘
- 将index buffer清空,其中的文档生成一个新的segment,相当于一个refrsh操作
- 执行fsync操作,将内存中的segment写入磁盘
- 删除旧的translog文件
refresh发生的时机主要有以下几种情况:
- 间隔时间达到时,
- 通过index.settings.refresh_interval来设定,默认是1秒
- index.buffer占满时,
- 其大小通过indices.memory.index_buffer_size设置,
- 默认为jvm heap的10%,所有shard共享
- flush发生时也会发生refresh
flush发生的时机主要有以下几种情况:
- 间隔时间达到时,默认是30分钟
- 5.x之前可以通过index.translog.flush_threshold_period修改
- 之后发布的版本无法设置
- translog占满时,
- 其大小可以通过index.translog.flush_threshold_size控制,
- 默认是512MB每个index有自己的translog