深入理解elasticsearch增删改查数据的原理

本文深入剖析 Elasticsearch 的数据写入、读取和搜索机制,详细阐述数据如何在 shard 间高效同步,以及倒排索引在搜索中的应用。从数据写入内存缓存到磁盘文件的全过程,再到如何通过 refresh 操作实现数据快速可用,直至 commit 操作确保数据完整性和一致性,揭示 Elasticsearch 的近实时特性。同时,阐述了如何通过 docid 进行数据查询和删除/更新操作的底层原理,以及 merge 和 delete 操作如何优化索引管理。

1、es写入数据的基本原理及过程

假设es中的一个index,有3个shard,部署在3台机器上,如图1所示。

图1 es部署图

当客户端写入一条数据的时候,可以挑选任意一个节点去写,假设客户端把数据分发到了机器02上去了。此时es进程02就被称为协调节点(coordinating node)。

图2 es协调节点

协调节点此时就会对这这条数据做hash,假设这条数据hash完之后属于shard01,因为shard01 primary在es进程01上,es进程02就会把把请求转发给es进程01,shard01 primay就会来处理这条数据。

shard01 primay接受到写请求后,就会执行写数据功能,写完之后就会把所有的数据同步给replica node。

图3 primary shard同步数据到replica节点

协调节点如果发现primary node和所有replica node都搞定之后,就返回响应结果给客户端。

以上就是es写入数据的基本原理,不过如果只理解到这个程度,就太浅了。

比如primary shard具体是如何写数据的?

2、es写入数据的过程

primary shard接收到写入数据请求时,会先把数据写入内存buffer中,如果只写内存buffer,机器宕机了,数据就会丢失,所以同时还会把数据写入translog文件中去。

需要注意的是,此时客户端来搜索,是搜索不到这条数据的。

如果内存buffer满了,或者es会定时把内存buffer中的数据刷入到磁盘文件中去,默认间隔时间是1秒,所以每秒钟会产生一个segment file文件。当然,如果内存buffer中没有数据,就不会产生一个空的segment file文件了。

现在操作系统写文件不是直接进入磁盘文件的,是先写入os cache中。所以es执行refresh操作时,是先把内存buffer中的数据刷到os cache,进入操作系统级别的一个内存缓冲中去。

只要内存buffer中的数据被刷入os cache中,客户端执行搜索就可以搜索到了。所以为什么称es是近实时(NRT)的,就是这个原因,你向es中写入一条数据,一般1秒之后才会刷入os cache,才可以搜索到。

你也可以通过调用es的restful api或者Java api,手动执行一次refresh操作,手动将内存buffer中的数据刷入os cache中,让数据立马可以被搜索到。

数据刷入os cache中之后,内存buffer中的数据就会被清空,不会占据很大内存空间,但是translog日志文件是怎么处理的呢?

当translog日志文件大到一定程度的时候,就会执行commit操作。

commit操作的第一步,就是把buffer中的数据refresh到os cache中去,清空buffer。然后将一个commit point写入磁盘文件,里面标识着这个commit point 对应的所有segment file。同时强行将os cache中目前所有的数据都fsync到磁盘文件中去。最后清空现有translog日志文件,重启一个 translog,此时 commit 操作完成。

那么translog日志文件的作用是什么呢?

在执行commit操作之前,数据要么是停留在buffer中,要么是在os cache 中,无论是buffer还是os cache都是内存,一旦这台机器宕机了,内存中的数据就全丢了。所以需要将数据对应的操作写入一个专门的日志文件translog中,一旦此时机器宕机,再次重启的时候,es 会自动读取translog 日志文件中的数据,恢复到内存 buffer 和 os cache 中去。

translog其实也是先写入os cache的,默认每隔5秒刷一次到磁盘中去,所以默认情况下,可能有5秒的数据会仅仅停留在buffer或者translog文件的os cache 中,如果此时机器挂了,会丢失5秒钟的数据。但是这样性能比较好,最多丢5秒的数据。也可以将translog设置成每次写操作必须是直接fsync到磁盘,但是性能会差很多。

这个commit操作叫做flush。默认30分钟自动执行一次flush,但如果 translog过大,也会触发flush。flush操作就对应着commit的全过程,我们可以通过es api,手动执行flush操作,手动将os cache中的数据fsync强刷到磁盘上去。

图4 primary shard写入数据详细流程

总结一下,数据写入过程是先写入内存buffer,然后每隔1s,将数据refresh到os cache中,到了os cache数据就能被搜索到(所以我们才说 es 从写入到能被搜索到,中间有 1s 的延迟)。每隔5s,将数据写入translog文件(这样如果机器宕机,内存数据全没,最多会有 5s 的数据丢失),translog大到一定程度,或者默认每隔30分钟,会触发commit操作,将缓冲区的数据都 flush到segment file磁盘文件中。

另外需要说明下的是,数据写入 segment file 之后,同时就建立好了倒排索引。

3、es读取数据的过程

客户端如果是通过doc id来进行读取的,es就会根据doc id进行 hash,判断出来当时把 doc id 分配到了哪个 shard 上面去,从那个 shard 去查询。具体步骤如下:

  • 客户端发送请求到任意一个node,成为协调节点(coordinate node)。

  • 协调节点对doc id进行哈希路由,将请求转发到对应的node,此时会使用round-robin随机轮询算法,在primary shard以及其所有replica中随机选择一个,让读请求负载均衡。

  • 接收请求的node返回document给协调节点。

  • 协调节点返回document给客户端。

4、es搜索数据过程

es最强大的功能就是搜索,搜索是建立在倒排索引的基础上的,如果有伙伴们不知道什么是倒排索引,请自行百度。

比如你有这几条数据:

elasticsearch真强大

elasticsearch好难学啊

es特别赞

如果你搜索包含elasticsearch的document,es 就会给你返回:elasticsearch真强大 elasticsearch好难学啊,这两条数据。其具体搜索步骤是这样的:

  • 客户端发送请求到一个协调节点(coordinate node)。

  • 协调节点将搜索请求转发到所有的shard对应的primary shard 或replica shard。

  • 查询阶段(query phase):每个 shard 将自己的搜索结果(其实就是一些 doc id)返回给协调节点,由协调节点进行数据的合并、排序、分页等操作,生成最终结果。

  • 返回阶段(fetch phase):接着由协调节点根据doc id去各个节点上拉取实际的document 数据,最终返回给客户端。

需要注意的是:写请求是写入primary shard,然后同步给所有的replica shard;读请求可以从primary shard或replica shard读取,采用的是随机轮询算法。

5、es删除/更新数据底层原理

如果是删除操作,commit 的时候会生成一个 .del 文件,里面将某个 doc 标识为 deleted 状态,那么搜索的时候根据 .del 文件就知道这个doc是否被删除了。

如果是更新操作,就是将原来的doc 标识为deleted状态,然后新写入一条数据。

内存buffer每refresh一次,就会产生一个segment file,所以默认情况下1秒产生一个segment file,这样下来segment file 会越来越多,此时es会定期执行merge操作。

每次merge的时候,会将多个segment file合并成一个,同时这里会将标识为deleted的doc给物理删除掉,然后将新的segment file写入磁盘,这里会写一个commit point,标识所有新的segment file,然后打开segment file供搜索使用,同时删除旧的segment file。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值