ES 是如何写入一条数据的?

ES的前世今生

我们都知道elasticsearch 底层是 lucene,那 lucene 是什么呢?

lucene 是一种比较先进、功能很强大的搜索库,目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。但是如果直接基于 lucene 开发,非常复杂,即便写一些简单的功能,也要写大量的 Java 代码。

虽然 elasticsearch 基于 lucene,但是它隐藏了 lucene 的复杂性,提供了简单易用的 restful api 和其他各种语言的 api 接口,在分布式搜索领域大放异彩。ES是分布式的,并且支持 PB 级数据,搜索速度极快,那么你知道它为什么这么快吗?它写入一条数据的流程是怎样的呢?

ES写入数据

我们ES一般是集群部署,所以这里从集群的维度来说明。

  1. 客户端选择一个节点发送请求,这个节点就是数据节点也可能是客户端节点。
  2. 接收请求的节点对请求进行路由到有主分片的节点上去。
  3. 节点上的主分片写入数据,并将数据同步到副本。
  4. 当主分片和所有副本成功写入并返回ACK,返回响应给客户端。

下面我们来看看主分片写入数据的具体流程
在这里插入图片描述

  1. 请求到达主分片先写入内存 buffer,此刻该数据在 buffer 里的是搜索不到的,同时将数据写入 translog 日志文件。

translog 日志文件的作用是什么?你执行 commit 操作之前,数据要么是停留在 buffer 中,要么是停留在 os cache 中,无论是 buffer 还是 os cache 都是内存,一旦机器宕机,内存中的数据就全丢了。所以需要将数据对应的操作写入一个专门的日志文件 translog 中,用于恢复数据,同时translog 是顺序写,性能很高

translog 也是先写 os cache 的,默认每隔 5 秒刷一次到磁盘中去,所以最快情况会丢5秒数据,虽然也可以将 translog 设置成每次写操作必须是直接 fsync 到磁盘,但是性能会差很多。

  1. 如果 buffer 快满了,或者到一定时间(默认是1秒),就会将内存 buffer 数据 refresh 到一个新的 segment file 中,但是此时数据不是直接进入 segment file 磁盘文件,而是先进入 os cache,此刻数据就可以被搜索到了(为什么说ES是准实时的就是因为默认会隔1秒中才能被搜索到)

  2. 随着新的数据不断进入 buffer 和 translog,不断将 buffer 数据写入一个又一个新的 segment file 中去,每次 refresh 完 buffer 清空,translog 保留。translog 会变得越来越大。当 translog 达到一定长度的时候,就会触发 commit 操作。

  3. commit 会将 buffer 中现有数据 refresh 到 os cache 中去,清空 buffer。然后,将一个 commit point 写入磁盘文件,里面标识着这个 commit point 对应的所有 segment file,同时强行将 os cache 中目前所有的数据都 fsync 到磁盘文件中去。最后清空现有 translog 日志文件,重启一个 translog,这个过程也是我们常说的flush,默认 30 分钟自动执行一次,但如果 translog 过大,也会触发 flush。


以上就是数据写入过程了。

总结

从以上流程我们知道,搜索其实是基于os cache的,所以我们应该尽量调大系统的os cache,尽量使数据都停留在os cache中,这样可以极大地提高性能,顺带一说,segment file里面不只是数据,还保留了倒排索引结构,通过倒排索引我们可以快速定位文档,而怎么快速定位倒排索引呢?答案是字典树。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值