Elasticsearch如何动态维护一个不可变的倒排索引

上一篇文章中介绍了Elasticsearch中是如何搜索文本的,同时也简述了在es里面索引数据结构的特点不可变性。

索引不可变性的缺点限制了单个索引存储的最大数据量以及更新的频次,所以es面临的问题是如何解决倒排索引不可更新的特点而同时仍然保持不可变特性带来的好处。

答案就是使用多个索引

代替原来的每次重写整个索引,es里面采用方式是增加新的索引来反映最近的变化,然后查询的时候一次查询所有的倒排索引,从最早的一直到最新的,然后在合并结果返回。

在lucene里面一个索引是多个segment加上一个commit point文件组成,每个segment都是一个倒排索引,而commit point这个文件标记了所有的已知的segment文件。如下图所示:

注意lucene里面的index在es里面叫做shard,es里面的一个index可以包含多个shard,对es里面的一个索引查询在es底层会把查询请求发送到所有shard里面最后在把结果集合并并返回。

回到文章开头的问题,es如何利用多索引来解决更新的问题,下面我们看下数据被写入es的过程:

(1)当es收到一个写入或者更新的请求时,首先会把这个数据收集在内存的indexing buffer

(2)经过一定的间隔或者外部命令触发时,会在内存缓冲区生成新的segment。

(3)然后segment首先会被写到filesystem cache中,这个时候其实搜索就能搜到了。

(4)然后经过一段时间filesystem cache中的segment会被fsync到磁盘文件上并在commit point文件中记录新segment文件名称,同时新的segment会被打开确保搜索可见

(5)最终内存里面buffer区会被清空,并等待收集新的documnet。

如下图:

当收到查询请求时,所有的sengment包含内存和磁盘中的会被依次查询,最终聚合所有segment并准确计算每个document的相关性,上面的实现方式可以相对代价比较小的方法处理新增的document。

上面介绍的是新增数据的处理,接下来我们看下如果有删除和更新请求那么es是如何处理的。

首先我们知道sengments本身是不可变的,所以document是不能从旧的segments中移除,同时也不能被更新,那么es是如何处理删除和更新请求的呢?

在每次commit point时,es会生成一个后缀为.del的文件,这个文件标记了所有已经被删除的数据,在一条数据被删除时,es仅仅会在.del文件里面做个删除标记,被标记删除的数据仍然会被查询到,但是在最终返回结果之前,被标记删除的数据会被移除,这就是es里面删除的实现逻辑。

同理更新的逻辑也类似,当一个document被更新时,旧版本的document也会在.del文件里面被打上删除标记,新版本的document会被索引到一个新的segment里面,这个时候的查询会同时把两者都查询出来,但在最终返回结果之前被标记删除的旧版本数据会被移除掉。

以上就是es里面实现动态更新索引的内容,在这里我们能看到es里面更新和删除都类似于采用伪删除的策略来实现,到这里大家可能有个疑问,那些被标记删除的数据,什么时候才会被文件系统真正的清除,毕竟量大了还是对性能有一点影响的,这个在后面segment merge的文章中介绍。

原文发布于微信公众号 - 我是攻城师(woshigcs)

原文发表时间:2018-03-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏桥路_大数据

React Native打包apk错误: 找不到符号import com.facebook.react.ReactNativeHost;

60414
来自专栏文渊之博

SQLServer中的死锁的介绍

简介 什么是死锁?      我认为,死锁是由于两个对象在拥有一份资源的情况下申请另一份资源,而另一份资源恰好又是这两对象正持有的,导致两对象无法完成操作,且...

2355
来自专栏北京马哥教育

原创投稿 | 如何为Django添加中文搜索服务

云豆贴心提醒,本文阅读时间7分钟 在使用python的过程中,必然会设计到如何创建web应用,而搜索功能却最为常见,该文档包含了如何整合haystack,el...

28710
来自专栏IT笔记

Lepus搭建企业级数据库慢查询分析平台

Lepus的慢查询分析平台是独立于监控系统的模块,该功能需要使用percona-toolkit工具来采集和记录慢查询日志,并且需要部署一个我们提供的shell脚...

1262
来自专栏张狗蛋的技术之路

MySQL探秘(四):InnoDB的磁盘文件及落盘机制

 任何一个技术都有其底层的关键基础技术,这些关键技术很有可能也是其他技术的关键技术,学习这些底层技术,就可以一通百通,让你很快的掌握其他技术。如何在磁盘上存储数...

1845
来自专栏程序员同行者

优化mysql服务器

1192
来自专栏FreeBuf

搭建属于你自己的维基站点:MediaWiki

MediaWiki 是一个全球著名的开源的,运行于 PHP+MySQL 环境下的 wiki 程序 。例如,全球最大的 wiki 项目 维基百科,就是使用 Med...

5296
来自专栏LanceToBigData

MySQL集群(一)之主从复制

前面学完了JDBC,接下来带大家感受一下MySQL集群!其实什么是MySQL集群?简单的说就是一群机器(服务器)的集合,它们连在一起来工作。 其实各种数据库都有...

2655
来自专栏杨建荣的学习笔记

datapump简介(一) (r6笔记第2天)

datapump是在10g之后推出的新特性,无论从功能还是性能上,都有一定的改进,可以说在功能上丰富了很多,在性能上也提升了很多。可以说exp/imp中能实现的...

2605
来自专栏数据和云

性能优化:调整 I/O 相关的等待

编辑手记:对Oracle数据库进行调整优化,基本上最终都可以归结到I/O调整上,因此,了解如何来优化Oracle数据库的I/O对于一个DBA来说就显得至关重要。...

2613

扫码关注云+社区

领取腾讯云代金券