当别人问你Elasticsearch写入原理,看完这篇我不信你还不会

在了解Elasticsearch的写入原理之前先了解一下什么是refresh刷新时间间隔,那什么是刷新时间间隔呢,我们来举一个例子:

当我们新创建一条索引的时候,这条索引并不会立刻对搜索可见,他会现在内存buffer(缓冲区)中,等buffer满了,或者主动刷新时候才可以进行搜索,默认1000ms,可以理解为请求一个文档写入到ES中要过1秒才可以查询到。这也是ES为什么是近实时,而不是完全实时的原因。那主动刷新的时间间隔(refresh_interval)如何设定?

refresh_interval 参数,时间单位如下:

  • ms:毫秒
  • s:秒
  • m:分钟

设置时间刷新间隔

动态设置:可以针对指定的索引和时间参数动态设置。

PUT /{index}/_settings
{ 
  "refresh_interval": "2s" 
}

强制刷新:使用强制刷新可以使插入的这条文档立即可见。

POST test_write/_doc?refresh
{
  "name":"小姐姐",
  "age":20,
  "desc":"这是一个很美的小姐姐"
}

重置刷新间隔

PUT {index}/_settings
{
  "index" : {
    "refresh_interval" : null
  }
}

关闭间隔:关闭时间间隔后,可以说是永久的查不到,只有重新设置刷新时间间隔后才可以查询到新插入的文档,此场景可以适用于全量同步,等同步完了在打开。

PUT {index}/_settings
{
  "index" : {
    "refresh_interval" : -1
  }
}

调用接口刷新全部索引。

POST /_refresh

接下来,我们言归正传,开始我们的写入原理
在这里插入图片描述

  1. 每一个写请求,先写入内存buffer,同时写入translog文件,可以说是同时去执行两个流程。

  2. 等过了上边讲的refresh_interval刷新时间间隔后(默认1s刷新一次,并生成一个新的segment),或者Buffer写满(堆内存10%,最小48M)后也会写入index segment文件中,然后随着写入OS Cache,清空Buffer。OS Cache会返回一个状态,将segment文件设置问open,这时候刚刚写入的文档就可以被查到了。因为refreh会把文件写入内存中,所以假如此时断电了怎么半,那么这部分数据就丢了。所以es会定期执行flush操作,将缓存中segment文件全部写如磁盘并确保写入成功,同时写入一个commit point到磁盘。

  3. 当Translog文件足够大时候或者ES每隔30分钟,会强行flush操作,将segment文件fsync刷写磁盘,然后清空translog文件,并且重新生成一个。

关键名次解释:
Refresh_interval:刷新时间间隔。
Refrush:发生在JVM中,消耗堆内存,所以Refrush越少越好,可以增大refresh_interval刷新时间间隔,这时 ES写入时序性会变低,但是有利于提高查询性能。减小JVM压力,减轻服务器负载。
Segment File:每个Segment为倒排索引,每隔分片包含多个segment文件。分段数量上线为2^31,默认每秒都会生成一个segment文件,在分片中搜索其实是先搜索每个segment,最后将结果汇总到一起。Segment合并,
在合并进程中进程会选择将大小相似的Segment合并,然后在合并到更大的Segment中,期间不会中断索引和搜索。
TransLog:为了防止elasticsearch宕机造成数据丢失,保证其可靠性。
Fsync:将数据从OS Cache写入到OSDisk。
Commit Point:包含了当前可用segment。

来一波小插曲,上边说到Translog是为了防止elasticsearch宕机造成数据丢失,保证其可靠性,那么,Translog有多安全呢?

在文件被 fsync 到磁盘前,被写入的文件在重启或宕机之后就会丢失。默认 translog 是每 5 秒被 fsync 刷新到硬盘, 或者在每次写请求完成之后执行(index, delete, update, bulk操作)。这个过程在主分片和副本分片都会发生。这意味着在整个请求到主分片和副本分片的translog被 fsync 之前,你的客户端不会得到一个 200 OK 响应。
在每次请求后都执行一个 fsync 会带来一些性能损失,尽管实践表明这种损失相对较小(特别是bulk导入,它在一次请求中平摊了大量文档的开销)。
但是对于一些大容量,可以偶尔丢失几秒数据问题也并不严重的集群,使用异步的 fsync 还是比较有益的。比如,写入的数据被缓存到内存中,再每5秒执行一次 fsync 。
这个可以通过设置 durability 参数来启用async :

PUT /{index}/_settings
{
    "index.translog.durability": "async",
    "index.translog.sync_interval": "5s"
}

这个选项可以针对索引单独设置,并且可以动态进行修改。如果你决定使用异步 translog 的话,你需要保证在发生崩溃时,丢失掉 sync_interval 时间段的数据也无所谓。再决定使用这个async时一定要提前知道这个特性。
如果你不确定这个行为的后果,最好是使用默认的参数( “index.translog.durability”: “request” )来避免数据丢失。

参考:
https://www.elastic.co/guide/cn/elasticsearch/guide/current/near-real-time.html近实时搜索
https://www.elastic.co/guide/cn/elasticsearch/guide/current/translog.html持久化变更
https://www.elastic.co/guide/cn/elasticsearch/guide/current/merge-process.htmlSegment合并

写的如有不正确的地方欢迎大家指正

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值