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

在今天的文章中,我来详细描述一下 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.mfbz.cn/a/34912.html

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

相关文章

html前端输入框模糊查询

1、一个页面内多个模糊查询情况&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"UTF-8" /> <meta name"viewport" content"widthdevice-width, initial-scale1.0, user-scalable0, minimum-scale1.0, maximum-…

geoserver加载arcgis server瓦片地图显示异常问题处理

1.全能地图下载的瓦片conf.xml格式有问题首先要修改格式&#xff0c;conf.cdi文件也需要修改格式&#xff0c;修改为UTF-8或者UTF-8无BOM编码(不同的notepadd显示不同) 2. 下载的conf.xml坐标系默认从最小级别开始&#xff0c;一定要把前几级也补全&#xff0c;从0级开始 <L…

抖音SEO矩阵源码开发(一)

前言&#xff1a; 1.抖音SEO矩阵系统源码开发 是一项技术密集型工作&#xff0c;需要对大数据处理、人工智能等领域有深入了解。该系统开发过程中需要用到多种编程语言在服务器上安装LNMP环境&#xff0c;包括Linux操作系统、Nginx、MySQL、PHP等&#xff0c;如Java、Python等…

GitHub打不开的解决方案(超简单)

在国内&#xff0c;github官网经常面临打不开或访问极慢的问题&#xff0c;不挂梯子&#xff08;VPN&#xff0c;飞机&#xff0c;魔法&#xff09;使用体验极差&#xff0c;那有什么好办法解决GitHub官网访问不了的问题&#xff1f;今天小布教你几招轻松访问github官网。 git…

自定义MVC工作原理

目录 一、MVC二、MVC的演变2.1 极易MVCController层——Servletview层——JSP缺点&#xff1a;Servlet过多、代码冗余 2.2 简易MVCController层——Servletview层——JSP缺点&#xff1a;在Servlet中if语句冗余 2.3普易MVCController层——Servletview层——JSP缺点&#xff1a…

CentOS Linux的最佳替代方案(二)_AlmaLinux OS 8.6基础安装教程

文章目录 CentOS Linux的最佳替代方案&#xff08;二&#xff09;_AlmaLinux OS 8.6基础安装教程一 AlmaLinux介绍和发展历史二 AlmaLinux基础安装2.1 下载地址2.2 安装过程 三 AlmaLinux使用3.1 关闭selinux/firewalld3.2 替换默认源3.3 安装一些必要工具 CentOS Linux的最佳替…

uniapp - [全端兼容] 多选弹框选择器,弹框形式的列表多选选择器组件插件(底部弹框式列表多选功能,支持数据回显、动态数据、主题色等配置)

前言 网上的教程都太乱了,各种不兼容且 BUG 太多,注释也没有很难进行改造。 本文 实现了 uniapp 全端兼容的弹框多选选择器,从底部弹出列表项进行多选(可回显已选中和各种主题色、样式配置), 您可以直接复制代码,稍微改改样式就能用了。 如下图所示,数据列表(支持接口…

Centos7.9通过expect脚本批量修改H3C交换机配置

背景&#xff1a; 公司有几百台H3C二层交换机设备&#xff0c;当需要批量更改配置时非常的消耗工作量 解决&#xff1a; 通过一台Linux服务器&#xff0c;编写shell脚本&#xff0c;模拟Telnet至各台交换机&#xff0c;让一切变的很容易 1.首先在安装Telnet服务前需要检测centO…

途乐证券|股票低开好还是高开好?股票低开高走再回落什么意思?

对于一向不涨的股票&#xff0c;出资者常常感到困惑和不安。那么一向不涨的股票要留吗&#xff1f;什么股票更简单上涨&#xff1f;为我们预备了相关内容&#xff0c;以供参阅。 一向不涨的股票要留吗&#xff1f; 一向不涨的股票要不要留没有一个绝对的答案&#xff0c;出资者…

java开发微信公众平台之素材上传

微信公众平台官方文档 我在本地使用工具请求接口一切正常。 当我开始写代码的时候 我蒙了 后台怎么模拟form表单上传图片 放参考文章链接https://blog.csdn.net/subaiqiao/article/details/122059076 首先引入依赖 <dependency><groupId>com.squareup.okhttp3&l…

软件测试的生命周期、Bug

一、软件测试的生命周期 1、软件的生命周期&#xff1a; 需求分析&#xff1a;分析需求是否正确、完整。 设计&#xff1a;项目的上线时间、开始开发时间、测试时间、人员... 计划&#xff1a;设计技术文档、进行UI设计... 编码&#xff1a;写代码&#xff08;实现用户需求&am…

已上架的App在AppStore上无法搜索到的问题

已上架的App在AppStore上无法搜索到的问题 在AppStore上搜不到已经上架的应用程序可以采取以下解决办法&#xff1a; 拨打iTunes提供的支持电话&#xff1a;4006-701-855&#xff08;中国时间9:00-17:00&#xff09;。发送邮件给Review团队&#xff0c;在iTunes Connect登录后…

堆排序算法及其稳定性分析

堆排序算法及其稳定性分析 什么是堆排序&#xff1f; 堆排序是利用数据结构堆而设计的一种排序算法。 堆分为两种&#xff0c;大顶堆和小顶堆。 所谓大顶堆就是每个节点的值都大于或者等于其左右孩子节点的值。 小顶堆则是相反的&#xff0c;每个节点的值都小于或者等于其…

单片机STM32看门狗详解(嵌入式学习)

单片机STM32看门狗 什么是看门狗为什么需要看门狗&#xff1f;STM32CubeMX配置和应用示例独立看门狗&#xff08;IWDG&#xff09;窗口看门狗&#xff08;WWDG&#xff09; 注意事项 什么是看门狗 单片机STM32的看门狗&#xff08;Watchdog&#xff09;是一种硬件定时器&#…

Android中级——IPC

IPC IPC是什么&#xff1f;多进程带来的问题IPC前提SerializableParcelableBinder Android中的IPCBundle文件共享MessengerAIDLContentProviderSocket不同IPC优缺点 Binder连接池 IPC是什么&#xff1f; Inter-Process Communcation&#xff0c;含义为进程间通信或者跨进程通信…

【FFMPEG】AVFilter使用流程

流程图 核心类 AVFilterGraph ⽤于统合这整个滤波过程的结构体 AVFilter 滤波器&#xff0c;滤波器的实现是通过AVFilter以及位于其下的结构体/函数来维护的 AVFilterContext ⼀个滤波器实例&#xff0c;即使是同⼀个滤波器&#xff0c;但是在进⾏实际的滤波时&#xff0c;也…

易模为真人3D手办制作带来了创新

3d打印技术是一项近年来迅速发展的先进制造技术&#xff0c;逐渐在各个领域展现出无限的潜力。其中&#xff0c;3d打印真人手办成为了一个备受关注的领域。在市面上&#xff0c;我们常常可以看到一些热门动漫角色或明星的真人3d手办&#xff0c;逼真的细节和完美的再现度让人们…

实验室仪器管理系统/基于微信小程序的实验室仪器管理系统

摘 要 随着当今网络的发展&#xff0c;时代的进步&#xff0c;各行各业也在发生着变化&#xff0c;于是网络已经逐步进入人们的生活&#xff0c;给我们生活或者工作提供了新的方向新的可能。 本毕业设计的内容是设计实现一个实验室仪器管理系统。使用微信开发者是以java语言…

【机器学习】主成分分析实现案例 (PCA)

一、说明 这篇文章的目的是提供主成分分析&#xff08;PCA&#xff09;的完整和简化的解释。我们将逐步介绍它是如何工作的&#xff0c;这样每个人都可以理解并使用它&#xff0c;即使是那些没有强大数学背景的人。 PCA是网络上广泛覆盖的机器学习方法&#xff0c;并且有一些关…

3.Hive SQL数据定义语言(DDL)

1. 数据定义语言概述 1.1 常见的开发方式 &#xff08;1&#xff09; Hive CLI、Beeline CLI Hive自带的命令行客户端 优点&#xff1a;不需要额外安装 缺点&#xff1a;编写SQL环境恶劣&#xff0c;无有效提示&#xff0c;无语法高亮&#xff0c;误操作率高 &#xff08;2&…
最新文章