elasticsearch7.x 乐观锁

      ES中的文档是不可变更的。如果更新一个文档,会将文档标记为删除,同时增加一个全新的文档,与此同时文档的 version 字段也会加 1。

      ES 7.x 之后,对应的 version 让然保留着,但是内部乐观锁版本控制是通过另外两个新引入的字段来控制的,分别是:seq_no 和 primary_term,汉语翻译过来就是:序列号 和 主项。

   在创建一个新文档时,会为其分配一个初始化的序列号(_seq_no)和主项(_primary_term),如果对文档有新的变更,序列号会递增。只有在要操作的文档的序列号和主项为指定值时才会对文档执行指定操作,否则会返回 version_conflict_engine_exception 异常 和 状态码 409。

{
  "_index" : "test",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 10,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "failed" : 0
  },
  "_seq_no" : 9,
  "_primary_term" : 1
}

  更新

POST /test/_update/1?if_seq_no=8&if_primary_term=1
{
  "doc":{
    "age":30
  }
}

  异常信息

{
  "error": {
    "root_cause": [
      {
        "type": "version_conflict_engine_exception",
        "reason": "[1]: version conflict, required seqNo [8], primary term [1]. current document has seqNo [9] and primary term [1]",
        "index_uuid": "_7ob_yUnSRi_XmJXU552mQ",
        "shard": "0",
        "index": "test"
      }
    ],
    "type": "version_conflict_engine_exception",
    "reason": "[1]: version conflict, required seqNo [8], primary term [1]. current document has seqNo [9] and primary term [1]",
    "index_uuid": "_7ob_yUnSRi_XmJXU552mQ",
    "shard": "0",
    "index": "test"
  },
  "status": 409
}

  就保证了不会丢失序列号为11,主项为1的操作。

外部版本控制

  ES允许不使用内置的version进行版本控制,可以自定义使用外部的version,例如常见的使用Elasticsearch做数据查询加速的经典方案,关系型数据库作为主数据库,然后使用Elasticsearch做搜索数据,主数据会同步数据到Elasticsearch中,而主数据库并发控制,本身就是使用的乐观锁机制,有自己的一套version生成机制,数据同步到ES那里时,直接使用更方便。

  请求语法上加上version_type参数即可:

POST /test/_doc/3?version=2&version_type=external
{"age":123
}

  外部_version,只有当提供的version比es中的_version大的时候,才能完成修改。

  

posted on 2021-10-10 11:21  溪水静幽  阅读(748)  评论(0)    收藏  举报