• Elasticsearch文档版本冲突原理与解决


    一般我们在更新文档时,主要的操作流程时:读取文档->修改->提交保存。数据中心等保存的都是最新一次提交的内容。

    大部分时候,这都没有什么问题。但是如果两个或更多的请求同时修改一个文档时,非常容易产生冲突,因为上述的流程无法保证原子性,也不可能保证。
    冲突解决常用的两种策略:

      1. 悲观锁并发策略
        在关系性数据库中,通过阻塞并排队的方式,来避免发生冲突,例如在读取数据行时阻塞,来保证正在修改行数据的请求完成正常操作后,以读取到最新的数据。这种方式的前提假设是数据冲突更有可能发生。
      2. 乐观锁并发策略
        Elasticsearch中采用的是乐观锁的并发策略,这种方式的前期假设是数据冲突一般不会发生,从而避免阻塞数据请求。然而,在读和写之间,如果数据发生改变,更新就失败了,然后由程序决定如果进行后续的处理。

      Elasticsearch是分布式的,文档的创建/变更等都会同步到其他节点。由于其异步性和并发的特点,这些同步请求都是并行的,因此并不能保证数据的是按照修改顺序依次到达的。Elasticsearch保证了一个老版本的数据永远无法重写或覆盖更新版本的数据。在 index get 和 delete请求中,都存在一个 _version 字段。数据的变更均会导致_version的值增大。Elasticsearch通过该字段来保证小于该值的数据会被忽略掉。通过数字版本的方式也可以避免ABA的数据问题,即数据A修改为B而后又修改为A,对于应用端来说,数据是没有任何变化的。

    创建文档: 

    1 PUT /website/blog/1/_create
    2 {
    3   "title": "My first blog entry",
    4   "text":  "Just trying this out..."
    5 }

    获取文档:

     1 GET /website/blog/1
     2 结果:
     3 {
     4   "_index" :   "website",
     5   "_type" :    "blog",
     6   "_id" :      "1",
     7   "_version" : 1,
     8   "found" :    true,
     9   "_source" :  {
    10       "title": "My first blog entry",
    11       "text":  "Just trying this out..."
    12   }
    13 }

    此时 _version 为1

    修改数据:

    1 PUT /website/blog/1?version=1 
    2 {
    3   "title": "My first blog entry",
    4   "text":  "Starting to get the hang of this..."
    5 }
    1 {
    2   "_index":   "website",
    3   "_type":    "blog",
    4   "_id":      "1",
    5   "_version": 2
    6   "created":  false
    7 }

    此时操作成功。

    如果在_version为1的基础我们再次提交修改:

     1 {
     2    "error": {
     3       "root_cause": [
     4          {
     5             "type": "version_conflict_engine_exception",
     6             "reason": "[blog][1]: version conflict, current [2], provided [1]",
     7             "index": "website",
     8             "shard": "3"
     9          }
    10       ],
    11       "type": "version_conflict_engine_exception",
    12       "reason": "[blog][1]: version conflict, current [2], provided [1]",
    13       "index": "website",
    14       "shard": "3"
    15    },
    16    "status": 409
    17 }

    此时,显示存在版本冲突。此时应用可以据此作出相应的处理,获取最新数据Merge处理亦或其他处理方式。

    问题解决:在请求上加上retry_on_conflict的参数,在冲突发生时,重试提交数据:

    1 POST /website/pageviews/1/_update?retry_on_conflict=5 
    2 {
    3    //some update
    4 }
  • 相关阅读:
    SSH 远程执行任务
    redmine + git
    progit-cn
    bash keys
    性能优化挑战重重,鲲鹏 HPC 如何突破算力桎梏?
    基因组实现自动AI建模,华为云助力科研人员探索生命奥秘
    【华为云技术分享】从零搭建一个灰度发布环境
    全面拥抱 FastApi — 多应用程序项目结构规划
    【华为云技术分享】物体检测yolo3算法 学习笔记(1)
    【华为云技术分享】物体检测yolo3算法 学习笔记2
  • 原文地址:https://www.cnblogs.com/zgxblog/p/14236973.html
Copyright © 2020-2023  润新知