“ElasticSearch基础:并发控制”的版本间差异

来自Wikioe
跳到导航 跳到搜索
(建立内容为“category:ElasticSearch == 关于 == <syntaxhighlight lang="java" highlight=""> </syntaxhighlight>”的新页面)
 
无编辑摘要
第2行: 第2行:


== 关于 ==
== 关于 ==
一般类似 MySQL 都是通过加锁确保数据原子性,在 Elasticsearch 中主要是通过 '''乐观锁''' 确保文档的原子性。


<syntaxhighlight lang="java" highlight="">


Elasticsearch 的乐观锁是基于'''版本号'''实现的:文档的元数据中 '''_seq_no'''('''version''')代表当前文档的版本号,每次更新、删除文档的时候,版本号都会加 1。
* Elasticsearch 7.5.x 使用 '''_seq_no''' 结合 '''_primary_term''' 字段实现乐观锁控制。
=== 示例验证 ===
# 插入一个文档:
#: <syntaxhighlight lang="java" highlight="">
PUT /order/_doc/2
{
  "id": 1,
  "status": 1,
  "total_price": 100,
  "create_time": "2019-12-12 12:20:22"
}
</syntaxhighlight>
# 查询该文档,观察版本号:
#: <syntaxhighlight lang="java" highlight="">
GET /order/_doc/2
</syntaxhighlight>
#: <syntaxhighlight lang="java" highlight="6,7">
{
  "_index" : "order",
  "_type" : "_doc",
  "_id" : "2",
  "_version" : 1,
  "_seq_no" : 6, // 版本号是6
  "_primary_term" : 1, // 所在主分区是1
  "found" : true,
  "_source" : {
    "id" : 1,
    "status" : 1,
    "total_price" : 100,
    "create_time" : "2019-12-12 12:20:22"
  }
}
</syntaxhighlight>
# 以指定的版本号更新数据:
#: if_seq_no 参数指定文档的版本号,if_primary_term 参数指定文档所在的主分区,如果 ES 发现文档当前的版本号与指定的版本号相等,就会更新文档,否则直接忽略(报错)。
#: <syntaxhighlight lang="java" highlight="">
PUT /order/_doc/2?if_seq_no=6&if_primary_term=1
{
  "id": 1,
  "status": 2,
  "total_price": 300,
  "create_time": "2019-12-12 12:20:22"
}
</syntaxhighlight>
# 重复执行上面的语句,ES 就会输出下面的错误提示:版本冲突 (version conflict):
#: <syntaxhighlight lang="java" highlight="">
{
  "error": {
    "root_cause": [
      {
        "type": "version_conflict_engine_exception",
        "reason": "[2]: version conflict, required seqNo [6], primary term [1]. current document has seqNo [7] and primary term [1]",
        "index_uuid": "CRQJQH4uTA2ffetowYCMNA",
        "shard": "0",
        "index": "order"
      }
    ],
    "type": "version_conflict_engine_exception",
    "reason": "[2]: version conflict, required seqNo [6], primary term [1]. current document has seqNo [7] and primary term [1]",
    "index_uuid": "CRQJQH4uTA2ffetowYCMNA",
    "shard": "0",
    "index": "order"
  },
  "status": 409
}
</syntaxhighlight>
</syntaxhighlight>

2021年5月20日 (四) 20:57的版本


关于

一般类似 MySQL 都是通过加锁确保数据原子性,在 Elasticsearch 中主要是通过 乐观锁 确保文档的原子性。


Elasticsearch 的乐观锁是基于版本号实现的:文档的元数据中 _seq_noversion)代表当前文档的版本号,每次更新、删除文档的时候,版本号都会加 1。

  • Elasticsearch 7.5.x 使用 _seq_no 结合 _primary_term 字段实现乐观锁控制。

示例验证

  1. 插入一个文档:
    PUT /order/_doc/2
    {
      "id": 1,
      "status": 1,
      "total_price": 100,
      "create_time": "2019-12-12 12:20:22"
    }
    
  2. 查询该文档,观察版本号:
    GET /order/_doc/2
    
    {
      "_index" : "order",
      "_type" : "_doc",
      "_id" : "2",
      "_version" : 1, 
      "_seq_no" : 6, // 版本号是6
      "_primary_term" : 1, // 所在主分区是1
      "found" : true,
      "_source" : {
        "id" : 1,
        "status" : 1,
        "total_price" : 100,
        "create_time" : "2019-12-12 12:20:22"
      }
    }
    
  3. 以指定的版本号更新数据:
    if_seq_no 参数指定文档的版本号,if_primary_term 参数指定文档所在的主分区,如果 ES 发现文档当前的版本号与指定的版本号相等,就会更新文档,否则直接忽略(报错)。
    PUT /order/_doc/2?if_seq_no=6&if_primary_term=1
    {
      "id": 1,
      "status": 2,
      "total_price": 300,
      "create_time": "2019-12-12 12:20:22"
    }
    
  4. 重复执行上面的语句,ES 就会输出下面的错误提示:版本冲突 (version conflict):
    {
      "error": {
        "root_cause": [
          {
            "type": "version_conflict_engine_exception",
            "reason": "[2]: version conflict, required seqNo [6], primary term [1]. current document has seqNo [7] and primary term [1]",
            "index_uuid": "CRQJQH4uTA2ffetowYCMNA",
            "shard": "0",
            "index": "order"
          }
        ],
        "type": "version_conflict_engine_exception",
        "reason": "[2]: version conflict, required seqNo [6], primary term [1]. current document has seqNo [7] and primary term [1]",
        "index_uuid": "CRQJQH4uTA2ffetowYCMNA",
        "shard": "0",
        "index": "order"
      },
      "status": 409
    }