Elasticsearch学习笔记(五)—Elasticsearch写入流程解读

一、Elasticsearch写入请求流程

  1. 假设一个写入请求发到node1
  2. node1接收到请求,根据_routing或_id来计算数据该写到哪个分片上,并且根据集群状态中的信息找到该分片的主分片在哪个节点上。这里发送到node3
  3. node3接收到请求的时候,开始往主分片里写数据
  4. 主分片写入完成后,转发请求到该分片的副本分片所在节点(node1、node2),并等待返回结果
  5. 副本分片接收到请求后,开始写入,写入成功后会返回结果给主分片节点
  6. 主分片节点(node3)接收到返回请求后,会把写入成功返回给node1

上述流程会受到相关参数配置影响,比如是否等待副本分片复制完成,详细参考上一篇博客

二、Elasticsearch shard中的写入流程

  • 当我们对记录进行修改时,es会把数据同时写到内存缓存区和translog中。此时数据不能被搜索
  • 默认情况下,es每隔一秒钟执行一次refresh,可以通过参数index.refresh_interval来修改这个刷新间隔。refresh操作
    • 所有在内存缓冲区中的文档被写入到一个新的segment中,但是没有调用fsync,因此内存中的数据可能丢失
    • segment被打开使得里面的文档能够被搜索到
    • 清空内存缓冲区
  • segment是存储在系统缓存(page cache)中的,只有达到一个周期或者数据量达到一定值,才会flush到磁盘上。系统内存中的segment丢失,是可以通过translog来恢复的。flush操作
    • 往磁盘里写入commit point信息
    • 文件系统中的segment,fsync到磁盘
    • 清空translog文件(旧版本清除)

translog可以保证缓存中的segment的恢复,但translog也不是实时磁盘的,也就是说,内存中的translog丢了的话,也会有丢失数据的可能。所以translog也要进行flush。

translog的flush操作默认是默认是request,每次写入translog必须flush进行刷盘,这样就保证所有数据不会丢,但是性能很受影响。可以将操作改成async,按照配置进行fsync,默认5s强制对translog进行flush操作,最小值可配置100ms

translog在segment刷盘后,就不再需要它的数据恢复能力,如果故障,也可以从segment文件恢复,translog删除的时机:
translog大小超过512mb或者超过三十分钟,会对translog进行清理,这是之前版本的机制,在6.0之后,为了实现 SequenceIDs 机制,translog 不再被立即清除,默认规则512MB 大小和 12 小时的时间窗口,才会被清除掉。

如果让translog同步刷盘,或者配置100ms刷盘,可以最大程度保证数据的安全性,但是对性能影响太大,使用默认5s进行强制translog刷盘,如果主分片宕机,使用副本分片恢复数据

小结:

在shard中,每次写入顺序是先写入Lucene,再写入transLog
Elasticsearch通过transLog和副本来保障segment的安全性

三、Elasticsearch的实时性

Elasticsearch的主要应用场景就是实时,但Elasticsearch本身并非实时而是near-real-time(近实时)。也就是数据写入es后再1秒后才可以被读取。

这是因为es写入是建立索引文件,每次写入是先写内存缓冲区和translog日志,这时的数据是不能被搜索到的,只有在经过1秒执行refresh操作,生成segment文件,才可以对外提供查询。

Elasticsearch也可以保证实时查询,使用Get请求接读内存中尚未Flush到磁盘的translog,但是Get请求只支持通过doc_id进行查询,所以对于条件查询依然无法实现实时

四、Elasticsearch segment merge

ES每秒生成一个segment,一个小时就会产生3600个segment,这样看来会产生大量的segments,所以需要对这些segment进行合并。

同时,Lucene的segment一旦形成,是不允许再进行修改的,所以Elasticsearch中所谓的删除是通过在新的segment中打标记实现的。只有在触发segments merge,对多个segments进行合并成一个大的segment时,才会真正意义上删除掉数据

归并流程:
  • 通过算法触发segments merage,将多个小的segments合并成一个大的segment。在这期间对ES的功能没有任何影响,它是有独立的线程来完成的,但是会影响ES的性能
  • 合并过程中删除掉执行delete/update操作的原始doc,对新的大segment进行flush
  • 检索请求从小的segment转移到大的segment中,等所有的请求都从小的segment上转移到大segment上,删除原先小的segment
force merge

Elasticsearch也提供了API支持我们手动强制merge,但是要慎用,因为merge会占用很大的系统开销

curl -XPOST "http://localhost:9200/library/_forcemerge?max_num_segments=1

参数说明:

  • max_num_segments 期望merge到多少个segments,1的意思是强行merge到1个segment
  • only_expunge_deletes 只做清理有deleted的segments,即瘦身
  • flush 清理完执行一下flush,默认是true
参数配置

index.merge.scheduler.max_thread_count

默认:Math.min(4, Runtime.getRuntime().availableProcessors() / 2))。意思就是当cpu核数的一半大于4时,最多启动4个线程,否则启动cpu核数一半的线程数。性能不够,适当降低线程数

归并策略
  • index.merge.policy.floor_segment
    默认 2MB,小于这个大小的 segment,优先被归并。
  • index.merge.policy.max_merge_at_once
    默认一次最多归并 10 个 segments
  • index.merge.policy.max_merge_at_once_explicit
    默认 force merge 时一次最多归并 30 个 segments
  • index.merge.policy.max_merged_segment
    默认 5 GB,大于这个大小的 segment,不用参与归并。force merge 除外

实时性不高的场景,可以加大flush时间间隔,让segment文件尽可能大点,减少merge次数

参考:

Elasticsearch权威指南
https://blog.csdn.net/xiaoyu_bd/article/category/9267058

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值