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

这篇具有很好参考价值的文章主要介绍了Elasticsearch:文档版本控制和乐观并发控制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Elasticsearch:文档版本控制和乐观并发控制,Elasticsearch,Elastic,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。

Elasticsearch:文档版本控制和乐观并发控制,Elasticsearch,Elastic,elasticsearch,大数据,搜索引擎,全文检索,运维

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

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

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

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

Elasticsearch:文档版本控制和乐观并发控制,Elasticsearch,Elastic,elasticsearch,大数据,搜索引擎,全文检索,运维

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

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

让我们看一个例子。

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

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

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

GET /products/_doc/100

Elasticsearch:文档版本控制和乐观并发控制,Elasticsearch,Elastic,elasticsearch,大数据,搜索引擎,全文检索,运维

 

请注意结果中的 “_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
  }
}

Elasticsearch:文档版本控制和乐观并发控制,Elasticsearch,Elastic,elasticsearch,大数据,搜索引擎,全文检索,运维

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

Elasticsearch:文档版本控制和乐观并发控制,Elasticsearch,Elastic,elasticsearch,大数据,搜索引擎,全文检索,运维

 

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

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

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

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

这就是你如何使用 Elasticsearch 实现乐观并发控制。 根据你的具体用例,这可能并不总是必要的,但如果您有可能同时更新同一文档的进程或线程,那么绝对值得考虑这种方法。文章来源地址https://www.toymoban.com/news/detail-525123.html

到了这里,关于Elasticsearch:文档版本控制和乐观并发控制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Elasticsearch深入理解 并发写入导致版本冲突解决方案【实战】

         数据同步中,在使用阿里云Elasticsearch7.10.0版本的集群作为目标数据源时,在连续写入同一文档(document)出现版本冲突问题。 注意:以下所述均以阿里云7.10.0版本的Elasticsearch集群为前提(不同版本可能会稍有不同)       以生产环境的错误日志信息为例: ElasticsearchSta

    2023年04月18日
    浏览(44)
  • 如何在 EF Core 中使用乐观并发控制

    乐观并发控制是一种处理并发访问的数据的方法,它基于一种乐观的假设,即认为并发访问的数据冲突的概率很低。在乐观并发控制中,系统不会立即对并发访问的数据进行加锁,而是在数据被修改时,再检查是否有其他并发操作已经修改了数据。如果检测到冲突,系统 再采

    2024年02月04日
    浏览(43)
  • MySQL实战:解密乐观并发控制,确保数据操作不冲突

      概述: 乐观并发控制是处理数据访问并发的一种策略,通过在更新前检查版本号或时间戳,确保数据在事务间保持一致性。在MySQL示例中,通过比对版本号,如果发现其他事务已更新数据,则拒绝当前事务的修改,避免潜在的并发冲突。这种机制提高了数据一致性,典型应

    2024年03月13日
    浏览(34)
  • Mysql--技术文档--MVCC(Multi-Version Concurrency Control | 多版本并发控制)

            MVCC(Multi-Version Concurrency Control)是一种并发控制机制,用于解决并发访问数据库时的数据一致性和隔离性问题。MVCC允许多个事务同时读取数据库的同一数据,而不会相互干扰或导致冲突。         在传统的并发控制机制中,如锁定机制,事务会对读取和写入

    2024年02月11日
    浏览(42)
  • elasticSearch7版本文档中文属性模糊查询不准确

    1、问题:es文档中的某个属性值name的值如下所示 name\\\":\\\"catalog=Catalog(value=699015935012372480, displayName=/默认分组), status=3, updaterName=admin, updateTime=2023-02-01 14:33:17)status:已发布” 通过java模糊查询的api(QueryBuilders.fuzzyQuery)查询name为“已”的时候可以查询,查询为“已发布”的时候查

    2024年02月02日
    浏览(55)
  • Elasticsearch 为什么会产生文档版本冲突?如何避免?

    先让大家直观的看到 Elasticsearch 文档版本冲突。 1.1 场景1:create 场景 1.2 场景2:批量更新场景模拟 模拟脚本1:循环写入数据 index.sh。 模拟脚本2:循环update_by_query 批量更新数据 update.sh。 由于:写入脚本 index.sh 比更新脚本 update.sh (执行一次,休眠1秒)执行要快,所以更新

    2023年04月08日
    浏览(48)
  • Elasticsearch7.8.0版本入门—— 高亮查询文档(高级查询)

    在 Postman 中,向 ES 服务器发 POST 请求 :http://localhost:9200/user/_doc/ 1 ,请求体内容为: 在 Postman 中,向 ES 服务器发 POST 请求 :http://localhost:9200/user/_doc/ 2 ,请求体内容为: 在 Postman 中,向 ES 服务器发 POST 请求 :http://localhost:9200/user/_doc/ 3 ,请求体内容为: 在 Postman 中,向

    2024年02月01日
    浏览(59)
  • Elasticsearch:解决并发写入导致版本冲突异常version_conflict_engine_exception

         数据同步中,在使用阿里云Elasticsearch7.10.0版本的集群作为目标数据源时,在连续写入同一文档(document)出现版本冲突问题。 注意:以下所述均以阿里云7.10.0版本的Elasticsearch集群为前提(不同版本可能会稍有不同)       以生产环境的错误日志信息为例: ElasticsearchSta

    2024年02月08日
    浏览(44)
  • Elasticsearch7.8.0版本入门—— 完全匹配查询文档(高级查询)

    在 Postman 中,向 ES 服务器发 POST 请求 :http://localhost:9200/user/_doc/ 1 ,请求体内容为: 在 Postman 中,向 ES 服务器发 POST 请求 :http://localhost:9200/user/_doc/ 2 ,请求体内容为: 在 Postman 中,向 ES 服务器发 POST 请求 :http://localhost:9200/user/_doc/ 3 ,请求体内容为: 在 Postman 中,向

    2023年04月24日
    浏览(51)
  • 怎样查询 elasticsearch es doc 文档中的 version 版本号

    参考链接:https://stackoverflow.com/questions/39016589/how-to-get-the-docs-version-field 记录一下: 需要加一个 version=true 的参数,返回结果中就会返回 version 。 返回结果:

    2024年02月16日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包