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

2024-05-15 02:58

本文主要是介绍Elasticsearch如何动态维护一个不可变的倒排索引,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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


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


答案就是使用多个索引

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

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


[img]http://dl2.iteye.com/upload/attachment/0129/1489/486c12c3-c8f0-3781-bc92-6b3a7caa77cb.png[/img]


注意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。


如下图:

[img]http://dl2.iteye.com/upload/attachment/0129/1491/8201a127-9d97-3ae1-9aa7-cf6f84a39bf5.png[/img]

[img]http://dl2.iteye.com/upload/attachment/0129/1493/85ad0abb-4c41-3ab3-b866-b46e5c2a8cd5.png[/img]



当收到查询请求时,所有的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的文章中介绍。

[b][color=green][size=large] 有什么问题可以扫码关注微信公众号:我是攻城师(woshigcs),在后台留言咨询。 技术债不能欠,健康债更不能欠, 求道之路,与君同行。 [/size][/color][/b] [img]http://dl2.iteye.com/upload/attachment/0104/9948/3214000f-5633-3c17-a3d7-83ebda9aebff.jpg[/img]

这篇关于Elasticsearch如何动态维护一个不可变的倒排索引的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/990617

相关文章

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

MySQL 索引简介及常见的索引类型有哪些

《MySQL索引简介及常见的索引类型有哪些》MySQL索引是加速数据检索的特殊结构,用于存储列值与位置信息,常见的索引类型包括:主键索引、唯一索引、普通索引、复合索引、全文索引和空间索引等,本文介绍... 目录什么是 mysql 的索引?常见的索引类型有哪些?总结性回答详细解释1. MySQL 索引的概念2

Oracle查询表结构建表语句索引等方式

《Oracle查询表结构建表语句索引等方式》使用USER_TAB_COLUMNS查询表结构可避免系统隐藏字段(如LISTUSER的CLOB与VARCHAR2同名字段),这些字段可能为dbms_lob.... 目录oracle查询表结构建表语句索引1.用“USER_TAB_COLUMNS”查询表结构2.用“a

MySQL 强制使用特定索引的操作

《MySQL强制使用特定索引的操作》MySQL可通过FORCEINDEX、USEINDEX等语法强制查询使用特定索引,但优化器可能不采纳,需结合EXPLAIN分析执行计划,避免性能下降,注意版本差异... 目录1. 使用FORCE INDEX语法2. 使用USE INDEX语法3. 使用IGNORE IND

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

MySQL逻辑删除与唯一索引冲突解决方案

《MySQL逻辑删除与唯一索引冲突解决方案》本文探讨MySQL逻辑删除与唯一索引冲突问题,提出四种解决方案:复合索引+时间戳、修改唯一字段、历史表、业务层校验,推荐方案1和方案3,适用于不同场景,感兴... 目录问题背景问题复现解决方案解决方案1.复合唯一索引 + 时间戳删除字段解决方案2:删除后修改唯一字

浅谈mysql的not exists走不走索引

《浅谈mysql的notexists走不走索引》在MySQL中,​NOTEXISTS子句是否使用索引取决于子查询中关联字段是否建立了合适的索引,下面就来介绍一下mysql的notexists走不走索... 在mysql中,​NOT EXISTS子句是否使用索引取决于子查询中关联字段是否建立了合适的索引。以下

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

MySQL之InnoDB存储引擎中的索引用法及说明

《MySQL之InnoDB存储引擎中的索引用法及说明》:本文主要介绍MySQL之InnoDB存储引擎中的索引用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录1、背景2、准备3、正篇【1】存储用户记录的数据页【2】存储目录项记录的数据页【3】聚簇索引【4】二

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决