ElasticSearch - 分布式文档索引、搜索、更新和删除文档的过程

news2025/8/6 4:49:09

文章目录

    • 1. 分布式文档存储
      • 1. 路由一个文档到一个分片中
      • 2. 主分片和副本分片如何交互
      • 3. 新建、索引和删除文档
      • 4. 取回一个文档
      • 5. 局部更新文档
    • 2. ElasticSearch相关问题
      • 1. 路由计算方式?
      • 2. 分片控制
      • 3. 分布式文档写入(索引)的过程?
      • 4. 分布式文档搜索的过程?
      • 5. 分布式文档更新和删除的过程?

1. 分布式文档存储

1. 路由一个文档到一个分片中

当索引一个文档的时候,文档会被存储到一个主分片中。 Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?当我们创建文档时,它如何决定这个文档应当被存储在分片 1 还是分片 2 中呢?

首先这肯定不会是随机的,否则将来要获取文档的时候我们就不知道从何处寻找了。实际上,这个过程是根据下面这个公式决定的:

shard = hash(routing) % number_of_primary_shards

routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值。 routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到 余数 。这个分布在 0number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。

这就解释了为什么我们要在创建索引的时候就确定好主分片的数量 并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。

所有的文档 API( getindexdeletebulkupdate 以及 mget )都接受一个叫做 routing 的路由参数 ,通过这个参数我们可以自定义文档到分片的映射。一个自定义的路由参数可以用来确保所有相关的文档——例如所有属于同一个用户的文档——都被存储到同一个分片中。

2. 主分片和副本分片如何交互

为了说明目的, 我们 假设有一个集群由三个节点组成。 它包含一个叫 blogs 的索引,有两个主分片,每个主分片有两个副本分片。相同分片的副本不会放在同一节点,所以我们的集群看起来像 Figure 8, “有三个节点和一个索引的集群”

在这里插入图片描述

我们可以发送请求到集群中的任一节点。 每个节点都有能力处理任意请求。 每个节点都知道集群中任一文档位置,所以可以直接将请求转发到需要的节点上。 在下面的例子中,将所有的请求发送到 Node 1 ,我们将其称为 协调节点(coordinating node)

3. 新建、索引和删除文档

新建、索引和删除 请求都是 操作, 必须在主分片上面完成之后才能被复制到相关的副本分片,如下图所示 Figure 9, “新建、索引和删除单个文档” .

在这里插入图片描述

以下是在主副分片和任何副本分片上面 成功新建,索引和删除文档所需要的步骤顺序:

  1. 客户端向 Node 1 发送新建、索引或者删除请求。
  2. 节点使用文档的 _id 确定文档属于分片 0 。请求会被转发到 Node 3,因为分片 0 的主分片目前被分配在 Node 3 上。
  3. Node 3 在主分片上面执行请求。如果成功了,它将请求并行转发到 Node 1Node 2 的副本分片上。一旦所有的副本分片都报告成功, Node 3 将向协调节点报告成功,协调节点向客户端报告成功。

在客户端收到成功响应时,文档变更已经在主分片和所有副本分片执行完成,变更是安全的。

4. 取回一个文档

可以从主分片或者从其它任意副本分片检索文档 ,如下图所示 Figure 10, “取回单个文档” .

在这里插入图片描述

以下是从主分片或者副本分片检索文档的步骤顺序:

1、客户端向 Node 1 发送获取请求。

2、节点使用文档的 _id 来确定文档属于分片 0 。分片 0 的副本分片存在于所有的三个节点上。 在这种情况下,它将请求转发到 Node 2

3、Node 2 将文档返回给 Node 1 ,然后将文档返回给客户端。

在处理读取请求时,协调结点在每次请求的时候都会通过轮询所有的副本分片来达到负载均衡。

在文档被检索时,已经被索引的文档可能已经存在于主分片上但是还没有复制到副本分片。 在这种情况下,副本分片可能会报告文档不存在,但是主分片可能成功返回文档。 一旦索引请求成功返回给用户,文档在主分片和副本分片都是可用的。

5. 局部更新文档

如 Figure 11, “局部更新文档” 所示,update API 结合了先前说明的读取和写入模式。

在这里插入图片描述

以下是部分更新一个文档的步骤:

  1. 客户端向 Node 1 发送更新请求。
  2. 它将请求转发到主分片所在的 Node 3
  3. Node 3 从主分片检索文档,修改 _source 字段中的 JSON ,并且尝试重新索引主分片的文档。 如果文档已经被另一个进程修改,它会重试步骤 3 ,超过 retry_on_conflict 次后放弃。
  4. 如果 Node 3 成功地更新文档,它将新版本的文档并行转发到 Node 1Node 2 上的副本分片,重新建立索引。 一旦所有副本分片都返回成功, Node 3 向协调节点也返回成功,协调节点向客户端返回成功。

当主分片把更改转发到副本分片时, 它不会转发更新请求。 相反,它转发完整文档的新版本。请记住,这些更改将会异步转发到副本分片,并且不能保证它们以发送它们相同的顺序到达。 如果Elasticsearch仅转发更改请求,则可能以错误的顺序应用更改,导致得到损坏的文档。

2. ElasticSearch相关问题

1. 路由计算方式?

1.1 路由解决的问题

当索引一个文档的时候,文档会被存储到一个主分片中。 Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?当我们创建文档时,它如何决定这个文档应当被存储在分片 P0还是P1P2中呢?

在这里插入图片描述

首先这肯定不会是随机的,否则将来要获取文档的时候我们就不知道从何处寻找了。实际上,这个过程是根据下面这个公式决定的:

shard = hash(routing) % number_of_primary_shards

routing 是一个可变值,默认是文档的 id ,也可以设置成一个自定义的值。 routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到余数 。这个分布在 0number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。

在这里插入图片描述

这就解释了为什么我们要在创建索引的时候就确定好主分片的数量并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。

你可能觉得由于Elasticsearch主分片数量是固定的会使索引难以进行扩容。实际上当你需要时有很多技巧可以轻松实现扩容。

所有的文档 APIgetindexdeletebulkupdate 以及 mget )都接受一个叫做 routing 的路由参数 ,通过这个参数我们可以自定义文档到分片的映射。一个自定义的路由参数可以用来确保所有相关的文档——例如所有属于同一个用户的文档——都被存储到同一个分片中。相同的路由值总是指向同一个分片。换个说法就是:“之前使用某个路由值将文档存放在特定的分片上,那么搜索时,也去相应的分片查找该文档。”

1.2 路由实战

通过路由控制Elasticsearch,选择将文档发送到哪个主分片。此时需要指定路由参数routing。路由参数值无关紧要,可以选择任何值。重要的是在将不同文档放到同一个分片上时,需要使用相同的值。简单地说,给不同的文档使用相同的路由参数值可以确保这些文档被索引到相同分片中。向Elasticsearch提供路由信息有多种途径。最简单的办法是在索引文档时加一个routing URI参数。例如:
在这里插入图片描述

查询时,请求会被发送至所有的分片,所以最关键的事情就是使用一个能均匀分发数据的算法,让每个分片都包含差不多数量的文档。并不希望某个分片持有99%的数据,而另一个分片持有剩下的1%,这样做极其低效。

2. 分片控制

索引一个文档时,这个文档会被存储到主分片中,主分片再将数据拷贝到副本分片中,而主分片和各个副本分片都在不同的节点上,所以每个节点上都有zhangsan这个文档数据,那我们要到哪个节点上获取这个文档数据呢?

实际上,我们可以发送请求到集群中的任一节点。 每个节点都有能力处理任意请求。 每个节点都知道集群中任一文档位置,所以可以直接将请求转发到需要的节点上。 将所有的请求发送到节点 1,我们将其称为协调节点。

在这里插入图片描述

但是,当发送请求的时候, 为了扩展负载,更好的做法是轮询集群中所有的节点

3. 分布式文档写入(索引)的过程?

新建、索引和删除 请求都是写操作,必须在主分片上面完成之后才能被复制到相关的副本分片,如图所示:新建,索引和删除单个文档

在这里插入图片描述

以下是在主副分片和任何副本分片上面成功新建,索引和删除文档所需要的步骤顺序:

① 客户端向 节点 1 发送新建文档请求 (节点 1就是协调节点)。

② 协调节点根据文档的 id 确定文档属于分片 0 (路由计算)。请求会被转发到 节点 2,因为分片0的主分片目前被分配在 节点 2 上。

节点 2 在主分片上面执行请求写入文档。如果成功了,它将请求并行转发到 节点 1节点 3 的副本分片上。一旦所有的副本分片都报告写入成功, 节点 2 将向协调节点报告成功,协调节点向客户端报告成功。

在客户端收到成功响应时,文档变更已经在主分片和所有副本分片执行完成,变更是安全的。

当协调节点接收到来自客户端对某个索引的写入文档请求时,该节点会根据路由算法将该文档映射到某个主分片上,然后将请求转发到该分片所在的节点。完成数据的存储后,该节点会将请求转发给该分片的其他副分片所在的节点,直到所有副分片节点全部完成写入,协调节点向客户端报告写入成功。

在这里插入图片描述

如图所示,一个包含3个节点的ES集群,假设索引中只有3个主分片和6个副分片,客户端向节点1发起向索引写入一条文档的请求,在本次请求中,节点1被称为协调节点。节点1判断数据应该映射到哪个分片上。假设将数据映射到分片1上,因为分片1的主分片在节点3上,因此节点1把请求转发到节点3上。节点3接收客户端的数据并进行存储,然后把请求转发到副分片1所在的节点1节点2上,当所有副分片所在的节点全部完成存储后,协调节点也就是节点1向客户端返回成功标志。

4. 分布式文档搜索的过程?

可以从主分片或者从其它任意副本分片检索文档 ,如下图所示:取回单个文档

在这里插入图片描述

以下是从主分片或者副本分片检索文档的步骤顺序:

① 客户端向 节点 1 发送获取请求。

② 节点使用文档的 id 来确定文档属于分片 0 。分片 0 的副本分片存在于所有的三个节点上。 在这种情况下,它将请求转发到 节点 3

节点 3 将文档返回给 节点 1 ,然后将文档返回给客户端。

在处理读取请求时,协调结点在每次请求的时候都会通过轮询所有的副本分片来达到负载均衡。

当协调节点接收到来自客户端的获取某个索引的某文档的请求时,协调节点会找到该文档所在的所有分片,然后根据轮询算法在主/副分片中选择一个分片并将请求转发给该分片所在的节点,该节点会将目标数据发送给协调节点,协调节点再将数据返回给客户端。
在这里插入图片描述
一个包含3个节点的ES集群,假设索引中只有3个主分片和6个副分片,客户端向节点1发起向索引获取文档的请求,在本次请求中,节点1被称为协调节点。节点1判断数据应该映射到哪个分片上。假设将数据映射到分片1上,分片1有主/副两种分片,分别在节点2节点1节点3上。假设此时协调节点的轮询算法选择的是节点3,那么它会将请求转发到节点3上,然后节点3会把数据传输给协调节点,也就是节点1,最后由节点1向客户端返回文档数据。

在文档被检索时,已经被索引的文档可能已经存在于主分片上但是还没有复制到副本分片。 在这种情况下,副本分片可能会报告文档不存在,但是主分片可能成功返回文档。 一旦索引请求成功返回给用户,文档在主分片和副本分片都是可用的。

5. 分布式文档更新和删除的过程?

update API 结合了读取和写入模式。
在这里插入图片描述
以下是部分更新一个文档的步骤:

① 客户端向 节点 1 发送更新请求。

② 节点使用文档的 id 来确定文档属于分片 0 ,它将请求转发到主分片所在的 节点 2

节点 2 从主分片检索文档,修改 _source 字段中的 JSON ,并且尝试重新索引主分片的文档。 如果文档已经被另一个进程修改,它会重试步骤 3 ,超过 retry_on_conflict 次后放弃。

④ 如果 节点 2 成功地更新文档,它将新版本的文档并行转发到 节点 1节点 3 上的副本分片,重新建立索引。 一旦所有副本分片都返回成功, 节点 2 向协调节点也返回成功,协调节点向客户端返回成功。

当主分片把更改转发到副本分片时, 它不会转发更新请求。 相反,它转发完整文档的新版本。请记住,这些更改将会异步转发到副本分片,并且不能保证它们以发送它们相同的顺序到达。 如果Elasticsearch仅转发更改请求,则可能以错误的顺序应用更改,导致得到损坏的文档。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自动化实战以及自动化性能测试

web自动化测试实战编写web自动化测试用例;创建自动化项目,根据用例来实现脚本无头模式使用selenium4自动化测试工具和junit5单元测试框架结合,如何实现的,以及有什么两点使用了junit5中提供的注解;避免生成过多的对象&…

轻量简单的团队协作工具有哪些?远程办公必备软件排行榜

前段时间的疫情不断反复,让不少企业和团队都开启了居家办公,无论是线上协作还是团队会议,都要使用大量的办公远程软件,因为突如其来的场景大转变,所以无形中也给大家增加了不少烦恼。 经历过了就有经验了,…

Docker安装Jenkins练习纪录一

Docker安装Jenkins练习记录参考博客准备资源centos7下载vmware下载jdk8下载Maven 下载FinalShell下载开始练习一些小问题参考博客 https://blog.csdn.net/lzc2644481789/article/details/124888223 https://blog.csdn.net/qq_52423918/article/details/125169577 准备资源 cen…

2023年天津体育学院专升本专业课考试考生考前防疫及入场须知

天津体育学院2023年高职升本科专业考试考生考前须知 一、防疫要求 1.考生要强化自我健康“第一责任人”的意识和责任,自觉履行考前每日健康监测义务。须于考前7天(3月8日前)下载《天津体育学院2023年高职升本科专业考试考生健康安全承诺书》&…

【微信小程序开发全流程】篇章0:基于JavaScript开发的校园综合类微信小程序的概览

基于JavaScript开发的校园综合类微信小程序的概览 本文仅供学习,未经同意请勿转载 一些说明:上述项目来源于笔者我本科大三阶段2019年电子设计课程项目,在这个项目中,我主要是负责的部分有前端,前后端的对接&#xf…

深入理解机器学习——偏差(Bias)与方差(Variance)

分类目录:《深入理解机器学习》总目录 偏差(Bias)与方差(Variance)是解释学习算法泛化性能的一种重要工具。偏差方差分解试图对学习算法的期望泛化错误率进行拆解,我们知道,算法在不同训练集上学…

兴达易控Modbus转Profinet网关连接1200Profinet转modbus接三菱A800变频器案例

下面介绍A800 变频器通过兴达易控modbus转profinet网关,使1200plc无需编程实现Profinet转modbus协议转换,把modbus变频器轻松组网 网络拓扑如下图 打开博图组态加载GSD文件,modbus转profinet网关从站接口接入到1200PLC上 配置modbus转profine…

【MyBatis】篇二.MyBatis查询与特殊SQL

文章目录1、MyBatis获取参数值case1-单个字面量类型的参数case2-多个字面量类型的参数case3-map集合类型的参数case4-实体类类型的参数case5-使用Param注解命名参数总结2、MyBatis的各种查询功能case1-查询结果是一个实体类对象case2-查询结果是一个List集合case3-查询单个数据…

杂记——16.idea中导入maven项目

这篇文章我们来讲一下如何从Gitee上拉取项目,并将该项目导入到idea中 目录 1.拉取项目 2.idea导入项目 3.更改相关的配置 3.1更改maven仓库 3.2更改数据库的连接池 1.拉取项目 第一步:找到相关的项目地址 如图所示,在Gitee上找到相关的…

FPGA时序约束(二)利用Quartus18对Altera进行时序约束

系列文章目录 FPGA时序约束(一)基本概念入门及简单语法 文章目录系列文章目录前言Quartus时序约束不进行时序约束的后果时序约束方法TimeQuest Timing Analyzer 工具来对工程添加约束。创建网表读取SDC文件创建时钟(Create Clock&#xff09…

八股总结(三)操作系统内存管理、进程线程、进程同步与通信、中断与异常、常用命令

layout: post title: 八股总结(三)操作系统内存管理、进程线程、进程同步与通信、中断与异常、常用命令 description: 八股总结(三)操作系统内存管理、进程线程、进程同步与通信、中断与异常、常用命令 tag: 八股总结 文章目录操作…

基础SQL语法及使用案例

通用SQL语法 SQL语句可以单行或多行书写,以分号结尾。SQL语句可以使用空格/缩进来增强语句的可读性。MySOL数据库的SQL语句不区分大小写,关键字建议使用大写。注释: 单行注释:--注释内容 或 #注释内容(MySQL特有) 多行注释&#…

英伟达驱动爆雷?CPU占用率过高怎么办?

又有一新驱动导致CPU占用率过高? 上周英伟达发布531.18显卡驱动,为大家带来了视频超分辨率技术,并为新发布的热门游戏《原子之心》提供支持。 但在安装新驱动后没过不久就有玩家反映,在游戏结束后会出现CPU占用率突然飙升到10%以…

YOLOv5源码逐行超详细注释与解读(2)——推理部分detect.py

前言 前面简单介绍了YOLOv5的项目目录结构(直通车:YOLOv5源码逐行超详细注释与解读(1)——项目目录结构解析),对项目整体有了大致了解。 今天要学习的是detect.py。通常这个文件是用来预测一张图片或者一…

TCL 拥抱云原生,实现 IT 成本治理优化

作者:行疾 TCL 工程师团队基于阿里云企业云原生 IT 成本治理方案沉淀了一套成熟的 IT 企业成本治理流程与系统,通过阿里云容器服务提供的开箱即用的成本洞察、资源智能画像等功能,进行业务成本拆分、闲置资源可视化发现,并制定弹性…

【开源库学习】从OkHttp到Retrofit(其二 Retrofit)

从OkHttp到Retrofit简单使用实现原理loadServiceMethodConverter简单使用 class RetrofitActivity : AppCompatActivity() {companion object {const val SERVER "https://www.xxx.com/"}var disposable:Disposable? null;override fun onCreate(savedInstanceSt…

Lesson 8.2 CART 分类树的建模流程与 sklearn 评估器参数详解

文章目录一、CART 决策树的分类流程1. CART 树的基本生长过程1.1 规则评估指标选取与设置1.2 决策树备选规则创建方法1.3 挑选最佳分类规则划分数据集1.4 决策树的生长过程2. CART 树的剪枝二、CART 分类树的 Scikit-Learn 快速实现方法与评估器参数详解1. CART 分类树的 sklea…

Linux线程概念

重新认识一下进程 在之前写过的与进程相关的博文中,都把进程看作是只有一个PCB的进程。如图: 而实际上,在Linux中,进程不止一个执行流,而是可能会有几个或很多个。同一个进程中,每一个执行流都指向同一个虚…

【C语言】3天速刷C语言(初识)

【声明】本篇博客只用于对与刚学习C语言的同学的一个初始了解,具体内容请继续关注本专栏后续内容。什么是C语言C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及…

模仿评论样式

主要用到了padding-left把左侧的空白给留出来,然后把头像定位到留出的空白位置。行内对齐样式,使用了display:inline-flex;align-items:center;图标本来要用字体比较方便,暂时用的从icon font下载的svg样式写的一塌糊涂,一点也没考…