深度解析:Elasticsearch写入请求处理流程

版本 Elasticsearch 8.x

原文链接:https://mp.weixin.qq.com/s/hZ_ZOLFUoRuWyqp47hqCgQ

今天来看下 Elasticsearch 中的写入流程。

不想看过程可以直接跳转文章末尾查看总结部分。最后附上个人理解的一个图。

从我们发出写入请求,到 Elasticsearch 接收请求,处理请求,保存数据到磁盘,这个过程中经历了哪些处理呢?Elasticsearch 又做了哪些操作?对于 Elasticsearch 写入一篇文档相信大家不陌生,但是Elasticsearch 的底层究竟是如何处理的呢,让我们一起来一探究竟。

写入流程

1、客户端发送写请求时,发送给任意一个节点,这个节点就是所谓的协调节点(coordinating node)。(对应图中的序号1

2、计算文档要写入的分片位置,使用 Hash 取模算法(最新版 Hash 算法)(对应图中序号2)。

routing_factor = num_routing_shards / num_primary_shards
shard_num = (hash(_routing) % num_routing_shards) / routing_factor

3、协调节点进行路由,将请求转发给对应的 primary sharding 所在的 datanode(对应图中序号2)。

4、datanode 节点上的 primary sharding 处理请求,写入数据到索引库,并且将数据同步到对应的 replica sharding(对应图中序号3)。

5、等 primary shardingreplica sharding 都保存好之后返回响应(对应图中序号 4,5,6)。

路由分片算法

7.13版本之前,计算方式如下:

shard_num = hash(_routing) % num_primary_shards

7.13 版本开始,不包括 7.13 ,计算方式就改为了上述步骤2的计算方式。

routing_factor = num_routing_shards / num_primary_shards
shard_num = (hash(_routing) % num_routing_shards) / routing_factor
  • num_routing_shards 就是配置文件中 index.number_of_routing_shard 的值。

  • num_primary_shard 就是配置文件中 index.number_of_shard 的值。

  • _routing 默认就是文档的 ID,但是我们可以自定义该路由值。

等待激活的分片

此处以 Create index API 举例说明,其中有一个请求参数 wait_for_active_shards
该参数的作用就是写入请求发送到ES之后,需要等待多少数量的分片处于激活状态后再继续执行后续操作。如果所需要数量的分片副本不足,则写入操作需等待并重试,直到所有的分片副本都已经启动或者发生超时。

默认情况下,写入操作仅等待主分片处于活动状态后继续执行(即 wait_for_active_shard=1)。

  • (可选)的字符串值。
  • 默认1
  • 可以设置为all,或者任意一个正整数,最多是索引的副本分片数+1(number_of_replicas+1)。

该设置极大的降低了写操作未写入所需数量分片副本的机会,但是并没有完全避免。

写入原理

先来一个官网的写入流程图(地址在文末获取)。

Elasticsearh 写入流程图

近实时

对于 Elasticsearch 的写入流程来说,就三部分:

1、写入到内存缓冲区。

2、写入打开新的 segment

3、写入 disk

为什么称为近实时,是因为在写入到内存缓冲区的时候,我们是还无法进行检索的,等到写入到segment之后,就可以进行检索到了,所以这是近实时的原因。

因为相对于写到磁盘,打开 segment 写入文件系统缓存的代价比写入磁盘的代价低的多。

第一步、写入文档到内存缓冲区(此时文档不可被检索)。

第二步、缓冲区的内容写入到 segment,但是还未提交(可被检索)。

在 Elasticsearch 中,写入和打开一个新segment的过程称为 refreshrefresh操作会自上次刷新(refresh)以来执行的所有操作都可用搜索。

refresh触发的方式有如下三种:

1、刷新间隔到了自动刷新。

2、URL增加?refresh参数,需要传或者true

3、调用Refresh API手动刷新

默认情况下,Elasticsearch 每秒定期刷新,但是仅限于在过去的30s内收到的一个或者多个 search请求。这个也就是近实时的一个点,文档的更改不会立即显示在下一次的检索中,需要等待 refresh 操作完成之后才可以检索出来。

我们可以通过如下方式触发refresh操作或者调整自动刷新的间隔。

POST /_refresh 
POST /blogs/_refresh

调整刷新间隔,每 30s 刷新

PUT /my_logs
{
  "settings": {
    "refresh_interval": "30s" 
  }
}

关闭自动刷新

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

设置为每秒自动刷新

PUT /my_logs/_settings
{ "refresh_interval": "1s" 

refresh_interval 需要一个 持续时间 值, 例如 1s (1 秒) 或 2m (2 分钟)。 一个绝对值 1 表示的是 1毫秒 --无疑会使你的集群陷入瘫痪。

段(segment)合并

由于 refresh 操作会每秒自动刷新生成一个新的段(segment),这样的话短时间内,segment会暴增,segment数量太多,每一个都会造成文件句柄、内存、CPU的大量消耗,还有一个更重要的点就是,每个检索请求也会轮流检查每一个segment所以segment越多,检索也就越慢。

Elasticsearch 通过在后台自动合并 segment 来解决这个问题的。小的segment被合并到大的segment,然后大的segment在被合并到更大的segment

segment 合并的时候会自动将已删除的文档从文件系统中删除,已经删除的文档或者更新文档的旧版本不会被合并到新的 segment中。

1、当 index 的时候,refresh操作会创建新的segment,并将segment打开以供检索。

2、合并进行会选择一小部分大小相似的segment,在后台将他们合并到更大的segment中,这个操作不会中断 indexsearch 操作。

optimize API

optimize API 不应该用在经常更新的索引上

optimize API 可以控制分片最大的 segment数量,对于有的索引,例如日志,每天、每周、每月的日志被单独存在一个索引上,老得索引一般都是只读的,也不太可能发生变化,所以我们就可以使用这个 optimize API 优化老的索引,将每个分片合并为一个单独的segment。这样既可以节省资源,也可以加快检索速度。

  • 合并索引中的每个分片为一个单独的段
POST /logstash-2014-10/_optimize?max_num_segments=1 

持久化

上述的refresh操作是 Elasticsearch 近实时 的原因,那么数据的持久化就要看fsync操作把数据从文件系统缓冲区flush到磁盘了。所以只有当translogfsync操作或者是提交时,translog中的数据才会持久化到磁盘。

如果没有持久化操作,当 Elasticsearch 宕机发生故障的时候,就会发生数据丢失了,所以 Elasticsearch 依赖于translog进行数据恢复。

在 Elasticsearch 进行提交操作的时候,成本是非常高的,所以策略就是在写入到内存缓冲区的时候,同步写入一份数据到translog,所有的indexdelete操作都会在内部的lucene索引处理后且未确认提交之前写入teanslog

如果发生了异常,当分片数据恢复时,已经确认提交但是并没有被上次lucene提交操作包含在内的最近操作就可以在translog中进行恢复。

Elasticsearch 的 flush操作是执行 Lucene提交并开始生成新的translog的过程,为了确保translog文件不能过大,flush操作在后台自动执行,否则在恢复的时候也会因为文件过大花费大量的时间。

对于translog有如下设置选项:

  • index.translog.durability 默认设置为request ,意思就是只有当主分片和副本分片fsync且提交translog之后,才会向客户端响应indexdeleteupdatebulk请求成功。

  • index.translog.durability 设置为async,则 Elasticsearch 会在每个index.translog.sync_interval 提交 translog,如果遇到节点恢复,则在这个区间执行的操作就可能丢失。

对于上述的几个参数,都可以动态更新

  • index.translog.sync_interval

translog fsync到磁盘并提交的频率。默认5s,不允许小于100ms

  • index.translog.durability

是否在每次indexdeleteupdatebulk操作之后提交translog

request: 默认,fsync 每次请求之后提交,如果发生故障,所有已确认的写入操作到已经提交到磁盘

async: fsync在后台每个sync_interval时间间隔提交。如果发生故障,自上次提交以来所有已确认的写入操作将被丢弃。

  • index.translog.flush_threshold_size

防止 translog 文件过大的设置,一旦达到设置的该值,就会发生 flush 操作,并生成一个新的 commit point。默认512mb

总结

1、一个文档被index之后,添加内存缓存区,同时写入 translog

2、refresh 操作完成后,缓存被清空,但是 translog 不会

  • 内存缓冲区的文档被写入到一个新的segment中,且没有进行fsync操作。
  • segment 打开,可供检索。
  • 内存缓冲区清空。

3、更多的文档被添加到内存缓冲区并追加到 translog

4、每隔一段时间,translog 变得越来越大,索引被刷新(flush),一个新的 translog 被创建,并且一个提交执行。

  • 所有内存缓冲区的文档都被写入到一个新的段。
  • 缓冲区被清空。
  • 一个提交点写入磁盘。
  • 文件系统缓存通过fsync被刷新(flush)。
  • 老的 translog 被删除。

translog 提供所有还没有被刷到磁盘的操作的一个持久化记录。当 Elasticsearch 启动的时候,它会从磁盘中使用的最后一个提交点(commit point)去恢复已知的 segment ,并且会重放 translog 中所有在最后一次提交后发生的变更操作。

translog 也被用来提供实时的CRUD,当我们通过ID进行查询、更新、删除一个文档、它会尝试在相应的 segment 中检索之前,首先检查 translog 中任何最近的变更操作。也就是说这个是可以实时获取到文档的最新版本。

最后送上一个我自己理解的图,参考了官网的描述,以及网上画的,如有错误欢迎指出。

如果感觉写的还不错,对你有帮助,欢迎点赞、转发、收藏,也可以评论互相交流。

也可以去搜索《醉鱼Java》点个关注,一起学习进步。

参考

https://www.elastic.co/guide/en/elasticsearch/reference/8.12/mapping-routing-field.html

https://www.elastic.co/guide/en/elasticsearch/reference/8.12/indices-create-index.html

https://www.elastic.co/guide/en/elasticsearch/reference/8.12/docs-index_.html#index-wait-for-active-shards

https://www.elastic.co/guide/en/elasticsearch/reference/current/images/data_processing_flow.png

https://www.elastic.co/guide/en/elasticsearch/reference/8.12/near-real-time.html

https://www.elastic.co/guide/cn/elasticsearch/guide/current/near-real-time.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-merge.html

https://www.elastic.co/guide/cn/elasticsearch/guide/current/translog.html

https://www.elastic.co/guide/cn/elasticsearch/guide/current/merge-process.html

https://blog.csdn.net/R_P_J/article/details/82254494?spm=a2c6h.12873639.article-detail.13.46227f70mJejca

http://www.uml.org.cn/bigdata/201801263.asp?spm=a2c6h.12873639.article-detail.10.46227f70mJejca&file=201801263.asp

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/483909.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

应急响应实战笔记03权限维持篇(7)

第7篇:常见WebShell管理工具 攻击者在入侵网站时,通常要通过各种方式写入Webshell,从而获得服务器的控制权限,比如执行系统命令、读取配置文件、窃取用户数据,篡改网站页面等操作。 本文介绍十款常用的Webshell管理工…

图论基础|深度优先dfs、广度优先bfs

dfs 与 bfs 区别 提到深度优先搜索(dfs),就不得不说和广度优先搜索(bfs)有什么区别 先来了解dfs的过程,很多录友可能对dfs(深度优先搜索),bfs(广度优先搜索…

K8S之DaemonSet控制器

DaemonSet控制器 概念、原理解读、应用场景概述工作原理典型的应用场景介绍DaemonSet 与 Deployment 的区别 解读资源清单文件实践案例 概念、原理解读、应用场景 概述 DaemonSet控制器能够确保K8S集群所有的节点都分别运行一个相同的pod副本; 当集群中增加node节…

【嵌入式】Docker镜像构建指南:引领应用部署的革新之路

🧑 作者简介:阿里巴巴嵌入式技术专家,深耕嵌入式人工智能领域,具备多年的嵌入式硬件产品研发管理经验。 📒 博客介绍:分享嵌入式开发领域的相关知识、经验、思考和感悟。提供嵌入式方向的学习指导、简历面…

绘制韦恩图

主要源于跟着Cell学作图 | 12.韦恩图(Vennerable包)-CSDN博客&#xff0c;增加了相关数据转换的处理。 韦恩图与upset差异 upset图&#xff1a;多个集合交集可视_upset图r语言代码自定义交集顺序-CSDN博客 rm(list ls()) #构建模型数据 group1 <- rep(c("1",…

AcWing 796. 子矩阵的和

这个题的重点是仿照一维的数组&#xff0c;所以a[N][N]也是从1索引开始的。画个图举个例子就非常清晰了 之所以不好理解是因为没画格子&#xff0c;一个格子代表一个点&#xff0c;就很好理解了。 java代码&#xff1a; import java.io.*; public class Main{static int N 1…

Java为什么是值传递?

Java为什么是值传递&#xff1f; 在我们调用方法的时候&#xff0c;通常会传递参数&#xff0c;那我们到底传递的是对象本身&#xff0c;还是仅仅是对象的拷贝对象呢&#xff1f; 先搞懂两个概念&#xff0c;形参和实参 形参和实参 实参&#xff08;实际参数&#xff0c;Ar…

【热门话题】ECMAScript vs JavaScript:理解两者间的联系与区别

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 ECMAScript vs JavaScript&#xff1a;理解两者间的联系与区别1. ECMAScript&am…

Java设计模式之单例模式(多种实现方式)

虽然写了很多年代码&#xff0c;但是说真的对设计模式不是很熟练&#xff0c;虽然平时也会用到一些&#xff0c;但是都没有深入研究过&#xff0c;所以趁现在有空练下手 这章主要讲单例模式&#xff0c;也是最简单的一种模式&#xff0c;但是因为spring中bean的广泛应用&#…

车载测试项目实践 USD诊断 CANoe工具使用

本周末2天的时间&#xff0c;可以线下带大家对车载项目&#xff1a; uds诊断进行实操训练和CANoe工具的灵活使用 本博主从事新能源汽车的研发部&#xff0c;主要是嵌入式方面的&#xff0c;对车载测试的底层逻辑非常熟悉。 需要项目或者CANoe工具实操的可以关注并私信我

解决长尾问题,BEV-CLIP:自动驾驶中复杂场景的多模态BEV检索方法

解决长尾问题&#xff0c;BEV-CLIP&#xff1a;自动驾驶中复杂场景的多模态BEV检索方法 理想汽车的工作&#xff0c;原文&#xff0c;BEV-CLIP: Multi-modal BEV Retrieval Methodology for Complex Scene in Autonomous Driving 链接&#xff1a;https://arxiv.org/pdf/2401.…

算法思想总结:位运算

创作不易&#xff0c;感谢三连支持&#xff01;&#xff01; 一、常见的位运算总结 标题 二、位1的个数 . - 力扣&#xff08;LeetCode&#xff09; 利用第七条特性&#xff1a;n&&#xff08;n-1&#xff09;干掉最后一个1&#xff0c;然后每次都用count去统计&#xff…

MySQL数据库的下载和安装以及命令行语法学习

MySQL数据库的下载和安装以及命令行语法学习 学习MYSQL&#xff0c;掌握住基础的SQL句型&#xff08;创建数据库、查看数据库列表、数据增、删、改、查等操作类型&#xff09; 首先要知道MySQL下载和安装方法&#xff1a; 提示&#xff1a;别嫌啰嗦&#xff0c;对于一个初识MY…

vue-cli3中拉取vue-cli2

vue-cli3中拉取vue-cli2 拉取 2.x 模板 (旧版本) Vue CLI > 3 和旧版使用了相同的 vue 命令&#xff0c;所以 Vue CLI 2 (vue-cli) 被覆盖了。如果你仍然需要使用旧版本的 vue init 功能&#xff0c;你可以全局安装一个桥接工具&#xff1a; npm install -g vue/cli-init…

linux源配置:ubuntu、centos;lspci与lsmod命令区别

1、ubuntu源配置 1&#xff09;先查电脑版本型号: lsb_release -c2&#xff09;再编辑源更新&#xff0c;源要与上面型号对应 参考&#xff1a;https://midoq.github.io/2022/05/30/Ubuntu20-04%E6%9B%B4%E6%8D%A2%E5%9B%BD%E5%86%85%E9%95%9C%E5%83%8F%E6%BA%90/ /etc/apt/…

MUNIK第二届功能安全及自动驾驶研讨会将在沪召开

2024年4月26日,由上海秒尼科技术服务有限公司(以下简称“Munik”)联合Parosoft主办的“第二届功能安全及自动驾驶研讨会”将在上海虹桥隆重开幕。 据了解,本次功能与自动驾驶安全研讨会,将聚焦在ISO 26262标准体系下,自动驾驶新形势下各个零部件供应商如何满足功能安全等相关重…

移除和替换任何内容:AI 驱动的图像修复工具 | 开源日报 No.204

Sanster/IOPaint Stars: 15.1k License: Apache-2.0 IOPaint 是一款由 SOTA AI 模型驱动的图像修复工具。 该项目解决了从图片中移除任何不需要的对象、瑕疵或人物&#xff0c;以及擦除和替换图片上任何内容&#xff08;由稳定扩散技术支持&#xff09;的问题。 完全免费且开…

赋能数据收集:从机票网站提取特价优惠的JavaScript技巧

背景介绍 在这个信息时代&#xff0c;数据的收集和分析对于旅游行业至关重要。在竞争激烈的市场中&#xff0c;实时获取最新的机票特价信息能够为旅行者和旅游企业带来巨大的优势。 随着机票价格的频繁波动&#xff0c;以及航空公司和旅行网站不断推出的限时特价优惠&#xff…

【Java - 框架 - HttpClient 5】(01) HttpClient 5 使用详细教程,代码示例 - 快速上手

HttpClient 5 使用详细教程&#xff0c;代码示例 - 快速上手 依赖 【Maven依赖】 <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5 --> <dependency><groupId>org.apache.httpcomponents.client5</groupId>…

网络分析(蓝桥杯,acwing,并查集)

题目描述&#xff1a; 小明正在做一个网络实验。 他设置了 n 台电脑&#xff0c;称为节点&#xff0c;用于收发和存储数据。 初始时&#xff0c;所有节点都是独立的&#xff0c;不存在任何连接。 小明可以通过网线将两个节点连接起来&#xff0c;连接后两个节点就可以互相通…