ElasticSearch 和 Inverted Index

Inverted Index


我们都知道,inverted index 是不可变的,如果要修改它,那么需要重写它。

不可变的好处:

  • 不需要锁来避免并发修改的问题
  • 可以被读到内核文件系统缓存中
  • 其他缓存(如 filter Cache)会在 Index 的生命周期内有效,因为不可变,所以数据变化时不需要重建
  • 不可变的大索引可以被压缩,节省IO和内存

然而,当遇到修改时,ES 如何使用 inverted index 呢?

Inverted Index in ES


ES 是使用多个 inverted index 来解决修改的问题。

首先我们先要了解,一个 Lucene Index 是由多个 segment 和一个 commit point 组成,而每个 segment 都是一个 inverted index.

但Lucene Index 在 es 中其实是一个 Shard,Es Index 则是一组 Shard。

在索引时:

  • 首先,如图一,新文档将被放在 Indexing Buffer 中。
  • 一段时间后,Buffer 会被作为新的 Segment 写到磁盘,Commit Point 也会被更新写入磁盘,使用 fsynced 方式确保数据被持久化了。
  • 如图二,Segment 也将被标记为可搜索的。
  • Buffer 被清除,重新接收新的文档。

图1

图一(如上)

图1

图二(如上)

查询时:

会查询每个 Segment,并汇总结果。

删除时:

由于 Segment 是不可变的,因此旧文档不能被更新和移除。
es 是在 Commit Point 用一个 .del 文件记录哪些 Segment 的哪些文档被删除了。
可知,文档删除其实只是标记一下,然后在查询结果中被过滤掉。

更新时:

更新和删除很类似,首先需要将旧文档标记删除,新版本的文档写到新的 Segment 中。
这样新文档在后续查询中将会被选中,旧文档则在返回结果前被过滤移除。

References


https://www.elastic.co/guide/en/elasticsearch/guide/current/inverted-index.html
https://www.elastic.co/guide/en/elasticsearch/guide/current/dynamic-indices.html
https://www.elastic.co/guide/en/elasticsearch/guide/current/making-text-searchable.html