Elasticsearch:文档版本控制和乐观并发控制

news2024/12/25 12:22:56

在今天的文章中,我来详细描述一下 Elasticsearch 文档的版本控制以及如何更新文档。你也可以阅读我之前的文章 “Elasticsearch:深刻理解文档中的 verision 及乐观并发控制”。

版本控制

我们知道 Elasticsearch 的每个文档都有一个相对应的版本。这个版本号在我们成功写入到 Elasticsearch 之后,就已经生成了:

PUT twitter/_doc/1
{
  "content": "This is Xiaoguo from Elastic"
}

上面命令返回如下的结果:

{
  "_index": "twitter",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 0,
  "_primary_term": 1
}

从上面的输出中来看,它的 _version 值为 1。当我们更新该文档后:

PUT twitter/_doc/1
{
  "content": "This is Xiaoguo, Liu from Elastic"
}

我们看到如下的返回结果:

{
  "_index": "twitter",
  "_id": "1",
  "_version": 2,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 1,
  "_primary_term": 1
}

上面的结果显示 _version 的值为 2。也就是说,当我们更新一次文档后,版本号就自动增加 1。

当我们在 Elasticsearch 中索引文档时,它会跟踪它们的版本。 重要的是要记住,Elasticsearch 的版本控制非常简单,并且不提供文档修改的完整历史记录。

它是如何工作的?

Elasticsearch 仅存储文档的最新版本。 因此,你无法返回过去并查看文档的先前版本。Elasticsearch 将名为 _version 的自定义字段存储为索引文档的元数据(metadata)。 该字段的初始值为 1,每次更新或删除文档时该字段都会增加 1。

删除文档时,Elasticsearch 默认保留版本号 60 秒。 如果在该时间范围内索引具有相同 ID 的新文档,版本号将会增加。 否则,它将被重置为 1。

当你使用文档 ID 获取文档时,您你在响应中看到此元数据字段。 但是,对于搜索请求,该字段不会自动包含在结果中。 但不用担心,如果需要,我们可以指示 Elasticsearch 包含它。

这种类型的版本控制称为 “内部版本控制”,但你还可以使用 “外部版本控制”。

外部版本控制专为你希望将文档版本保留在 Elasticsearch 外部(例如外部数据库中)的情况而设计。 例如,你可以使用关系数据库作为主要数据存储,并将数据索引到 Elasticsearch 中以进行搜索。 外部版本控制允许你指定 Elasticsearch 应存储的版本和版本类型。 你给出的版本必须是正整数。

那么,这个版本控制的目的是什么?

嗯,它实际上允许你跟踪文档被修改的次数,尽管这在大多数情况下可能不是特别有用。

老实说,“版本控制” 这个术语不再被普遍使用,或者不应该被普遍使用。 它曾经是一种乐观并发控制的技术。 现在,最好的做法是使用 primary 单词和 sequence number,而不是这种类型的版本控制。 另一方面,如果你有特定需求,_version 元数据字段仍然可用,尽管它的实用性受到极大限制。

那么,我为什么首先提出它呢?

你可能会以某种方式遇到此字段,特别是如果你正在使用使用旧版本 Elasticsearch 且需要乐观锁定的应用程序。

乐观并发控制

乐观并发控制是一种防止旧版本文档覆盖较新版本的技术。 这在处理无序到达的写入操作等场景时非常有用。

由于 Elasticsearch 是一个涉及网络的分布式系统,因此这种情况是可能的。 让我们看一个简单的例子来帮助你更好地掌握它。

想象一下,你正在使用电子商务平台,并且访问者将商品添加到购物车并完成结账流程。 现在,应用程序从 Elasticsearch 检索产品信息。 然而,在此期间,另一个访问者也完成了同一产品的结帐过程,并且 Web 服务器上的单独线程也检索产品信息。

此时,两个线程都返回了相同的产品信息。 第一个线程从产品的 in_stock 字段中减去一个,并使用 Elasticsearch API 更新文档。 这就是事情变得棘手的地方。 第二个线程尝试相同的操作,假设它保存 in_stock 字段的最新值。 然而,它没有意识到自最初检索产品信息以来该值已从 6 更新为 5。

现在,根据应用程序的不同,其后果可能完全不同。 在这种情况下,这可能意味着我们最终会出售实际上缺货的商品,这无疑会导致令人失望的客户体验。

那么,我们以后怎样才能避免类似的错误呢?

为了避免将来出现此类错误,我们必须确保如果文档自检索以来已被修改,我们的更新就会失败。 这就是版本控制发挥作用的地方,或者至少它曾经是解决方案。

过去,我们会使用文档检索附带的 _version 字段,并将其作为发送更新请求时的查询参数。

如果提供的版本与索引中存储的版本不匹配,更新操作将会失败。 虽然这种策略总体上运作良好,但当事情没有按计划进行时,它就会出现一些缺点。

这就是 primary terms 和 sequence nunber 用来解决这些问题的地方。 我们现在使用主要术语和序列号,而不是以前的方法。

让我们看一个例子。

当我们检索产品时,当前的 primary term 和序列号将包含在结果中。 要更新文档,我们可以获取这些值并将它们包含在 POST 请求中。 我们使用 “if_seq_no” 和 “if_primary_term” 参数来实现这一点。 然后,Elasticsearch 使用这两个值来确保我们不会意外覆盖自检索以来已修改的文档。 如果出现这种情况,操作会失败,我们可以重试该过程。

现在,让我们去 Kibana 见证这一过程。

首先,我们检索一个文档来展示结果中的 primary term 和 sequence number。

GET /products/_doc/100

 

请注意结果中的 “_primary_term” 和 “_seq_no” 字段。 如果你遵循的话,如果你看到的值有所不同,请不要担心。

我准备了另一个查询,它只是将 in_stock 字段更新为任意数字。

POST /products/_doc/100?if_primary_term=X&if_seq_no=X
{
  "doc": {
    "in_stock": 123
  }
}

正如你所看到的,我添加了两个查询参数,但还没有给它们一个合适的值。 让我们从查询结果中获取主要术语和序列号并填写它们。

首先,我们将参数 “if_primary_term” 设置为我们从结果中获得的主要项的值,并将第二个参数 “if_seq_no” 设置为结果中 “_seq_no” 的值,即 9。

这意味着,仅当文档的主要术语和序列号与提供的值匹配时,才会更新文档。

POST /products/_doc/100?if_primary_term=1&if_seq_no=9
{
  "doc": {
    "in_stock": 123
  }
}

正如我们在结果中看到的,文档已更新,新的序列号现在为 11。让我们再次运行查询而不更新序列号,只是为了证明这不起作用。

 

这次,我们遇到了一个错误,表明 primary term 和 sequence number 组合不匹配。 在这种情况下,我们是更新文档的人,但在你之前看到的场景中也可能会发生相同的情况。

通过采用这种技术,我们可以有效地避免文档在检索时更新的并发问题。

那么,当我们遇到这个错误时,我们该怎么办呢?

那么,当以这种方式更新文档时,你需要在应用程序中处理它。 这意味着你应该再次检索文档并在重试更新时使用新的 primary term 和 sequence number,并且不要忘记重新计算任何值,因为字段值可能已更改。

这就是你如何使用 Elasticsearch 实现乐观并发控制。 根据你的具体用例,这可能并不总是必要的,但如果您有可能同时更新同一文档的进程或线程,那么绝对值得考虑这种方法。

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

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

相关文章

GO微服务简介及特性介绍

微服务特性 一、微服务简介-构建单体应用 互联网技术发展迅速的今天,微服务倍受关注:文章、博客、社交媒体讨论和会议演讲都在谈论。与此同时,也有持怀疑态度的软件社区人员认为微服务没什么新鲜可言。反对者声称它的思想只是面向服务架构的…

Windows系统安装JAVA步骤流程(超详细)

超详细的Windows系统安装JAVA步骤流程,Windows操作系统安装java,先下载JDK,然后配置环境变量,阿里云百科分享详细安装流程如下: 目录 Window操作系统安装java流程 下载JDK 配置环境变量 JAVA_HOME 设置 PATH设置…

Centos安装RabbitMQ

#安装 yum install rabbitmq-server #启动 systemctl start rabbitmq-server #查看状态 systemctl status rabbitmg-server #安装管理插件 rabbitmg-plugins enable rabbitmg_management #新增admin账号 rabbitmqctl add_user admin admin #设置为管理员 rabbitmqctl set_user_…

电子电气架构——车载DoIP通信

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 人们会在生活中不断攻击你。他们的主要武器是向你灌输对自己的怀疑:你的价值、你的能力、你的潜力。他们往往会将此伪装成客观意见,但无一例外的是…

基于FreeRTOS的嵌入式设备管理关键技术研究及实现(学习二)

嵌入式操作系统FreeRTOS FreeRTOS是一个专门为轻量级嵌入式应用设计的迷你操作系统,它的主要功能由IPC、时钟管理、内存管理、任务通知以及任务调度等部分构成。 FreeRTOS的代码可以分解为三个主要区块:任务调度、通讯、硬件库。 任务调度:F…

windows环境安装robotframework-ride

在Windows环境下,可以通过以下步骤安装Robot Framework RIDE: 安装Python 首先,需要在Windows环境下安装Python。建议使用Python 3.x版本,可以从官方网站下载并安装:https://www.python.org/downloads/windows/ 安装w…

shiro登录认证

一,创建数据库 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0; -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS user; CREATE TABLE user ( uid int(11) NOT NULL AUTO_INCREMENT, uname va…

opencv中Rect()类与rectangle()函数详解

文章目录 Rect()矩形类1、实例化 Rect() 类:(1)构造函数: 2、Rect类的成员函数(1)rect.size() 和 rect.area() 和 rect.width() 和 rect.height(),用来描述矩形的宽度,高度&#xff…

SQL专家云回溯某时间段内的阻塞

背景 SQL专家云像“摄像头”一样,对环境、参数配置、服务器性能指标、活动会话、慢语句、磁盘空间、数据库文件、索引、作业、日志等几十个运行指标进行不同频率的实时采集,保存到SQL专家云自己的数据库中。因此可以随时对任何一个时间段进行回溯。 趋势…

基于C++、GDAL、OpenCV的矢量数据骨架线提取算法

基于C、GDAL、OpenCV的矢量数据骨架线提取算法 CGAL已经实现了该功能,但由于CGAL依赖于Boost库,编译后过大,因此本文所采用的这套方式实现骨架线提取功能。 效果: 思路: 1、将导入shp按照要素逐一拆分成新的shp 2、…

java中如何将一个集合list转成以逗号隔开的字符串

事例代码 代码&#xff1a; package com.air.app;import java.util.ArrayList; import java.util.List;public class ListToStringTest {public static void main(String[] args) {//定义list集合List<String> list new ArrayList<>();list.add("1");…

SolidUI AI生成可视化,开创性开源项目,版本0.1.0 功能讲解

文章目录 背景项目名字含义登录页含义产品思维0.1.0 版本内涵功能列表数据源管理项目管理设计页面 背景 随着文本生成图像的语言模型兴起&#xff0c;SolidUI想帮人们快速构建可视化工具&#xff0c;可视化内容包括2D,3D,3D场景&#xff0c;从而快速构三维数据演示场景。Solid…

多元分类预测 | Matlab基于麻雀算法优化深度置信网络(SSA-DBN)的分类预测,多特征输入模型,SSA-DBN分类预测

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元分类预测 | Matlab基于麻雀算法优化深度置信网络(SSA-DBN)的分类预测,多特征输入模型,SSA-DBN分类预测 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab,程…

linux_driver_day03

作业1 题目&#xff1a; 通过ioctl函数选择不同硬件的控制&#xff0c;LED 蜂鸣器 马达 风扇 代码&#xff1a; 代码太多只展示 led 部分&#xff0c;点击查看完整代码 led.c #include "led.h" #include "head.h"static void all_led_init(void);stati…

问题1:矩阵置零 问题2:搜索二维矩阵

问题1&#xff1a;矩阵置零 给定一个 *m* x *n* 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 解题思路&#xff1a; 1.先遍历一遍矩阵&#xff0c;将元素为0的行和列都标记为true 2.再遍历一遍矩阵&#xff0c…

Element 实现动态增加多个输入框并校验

文章目录 前言实现通过按钮动态增加表单并验证必填实现动态多个输入框为行内模式&#xff0c;其它为行外模式 前言 在做复杂的动态表单&#xff0c;实现业务动态变动&#xff0c;比如有一条需要动态添加的el-form-item中包含了多个输入框&#xff0c;并实现表单验证&#xff0…

Visual Studio Code 如何设置整体界面字体的大小?

在某次操作中&#xff0c;我不小心误点了什么&#xff0c;导致 Visual Studio Code 界面的字体变小了很小&#xff0c;如下图所示&#xff1a; 我想把字体调整回来&#xff0c;该如何操作呢&#xff1f; 首先&#xff0c;第一步&#xff0c;打开设置&#xff1a; 第二步&#…

MiniLED是什么?有怎样的发展前景

Mini LED又叫做“次毫米发光二极管”&#xff0c;也是LED器件的一种&#xff0c;其芯片尺寸介于50~200μm之间。Mini LED的组成包括Mini LED像素阵列以及驱动电路&#xff0c;而且像素中心间距的单元较小&#xff0c;仅为0.3-1.5mm单元。随着 Mini LED 显示技术的快速发展&…

Nginx+Tomcat负载均衡(反向代理)、动静分离集群

NginxTomcat负载均衡、动静分离 一、正向代理与反向代理二、负载均衡--with-stream #启用 stream模块&#xff0c;提供4层调度 一、正向代理与反向代理 Nginx:正向代理&#xff08;知道目标服务器&#xff09; 反向代理&#xff08;不知道目标服务器&#xff09; Nginx配置反…

QWebEngine应用---执行javascript

我们都知道现代前端技术是基于html、css和javascript进行显示交互的&#xff0c;其中html和css属于静态界面显示&#xff0c;辅以javascript使页面交互更丰富。浏览器作为前端页面显示的基石&#xff0c;提供一套显示、交互、调试的东西。QWebEngine同样也提供了这些功能&#…