segment
Lucene采用新文档生成新倒排索引,读时两边一起。
Lucene构建单个倒排索引称为segment,合并在一起称为Lucene Index,对应ES中的一个Shard
Lucene有专门文件记录所有segment信息,称为commit point文件
ES Index 与 Lucene Index整体视角对照图
文档搜索实时性 - refresh
· segment写入磁盘很耗时,借助缓存,先将segment在缓存中创建并开放查询,提升实时性,该过程成为refresh
· refresh之前会先存储在index buffer,refresh时将所有文档清空,并生成segment
· ES默认每一秒执行一次refresh,因此文档实时性被提高到1秒, 这就是为什么称为实时性搜索的原因
refresh发生的时机:
- 间隔时间到了,通过index.setting.refresh_interval来设定,默认1s
- index.buffer占满,其大小通过indices.memory.index_buffer_size设置,默认未jvm heap的10%,所有shard共享
- flush发生时也会触发refresh
文档搜索实时性 - translog
如果index buffer中还没来得及写入磁盘宕机,文档就无法恢复
- es引入 translog 机制,写入index buffer同时,将该操作写入translog (是否同步异步可选)
- translog文件会即时写入磁盘(fsync),6.x默认每个请求都落盘,可修改未5s一次,相关配置为index.translog.*
- es启动会检查translog文件,并从中恢复数据(类MYSQL的redolog)
文档搜索实时性 - flush
flush负责将内存中的segment写入磁盘,主要如下工作 (比较重)
- 将translog写入磁盘
- 清空index buffer,其中的文档生成一个新的segment,相当于refush
- 更新commit point 并写入磁盘
- 执行fsync操作,将内存中的segment写入磁盘
- 删除旧的translog
flush发生时机:
- 间隔时间到达,默认30分钟,5.x之前可以修改index.translog.flush_threshold_period修改,之后无法修改
- translog占满,大小由index.translog.flush_threshold_size控制,默认512mb,每个index有自己的translog
文档搜索实时性 - 删除与更新文档
segment一旦生成就不能更改,如何删除文档?
- Lucene专门维护一个.del文件,记录所有已经删除的文档,.del上记录的是文档在Lucene内部的id
- 在查询结果返回前会过滤掉.del中所有的文档
更新文档: 首先删除文档,再创建新文档
Segment merging
· 随着Segment的增多,由于一次查询Segment增多,查询速度会变慢
· es会定时会在后台进行Segment Merge操作,减少Segment的数量
· 通过force_merge api可以手动强制执行merge操作