【Elasticsearch7.0】文档接口之乐观锁并发控制

  |   0 评论   |   62 浏览

es是分布式的,当一个节点在做index,update,delete操作的时候,其他副本节点已经对文档进行了修改,生成了一个新的版本号,es是异步的,也是并发的,这些请求是并发过来的,而且他们的顺序还是不一致的,es保证了老版本号的文档不能覆盖新版本号的文档。
为了保证老版本号不能覆盖新版本号的文档,主分片会为每个请求分配一个序列号,序列号随着每个操作的增加而增加,因此新的序列号一定大于老的序列号,然后,Elasticsearch可以使用操作的序列号来确保新文档版本不会被分配了较小序列号的更改覆盖。如下示例会分配一个序列号和primary term。

curl -XPUT "http://127.0.0.1:9200/test/_doc/1567?pretty" -H "Content-Type:application/json" -d'
{
    "product" : "r2d2",
    "details" : "A resourceful astromech droid"
}'

返回值为:

{
  "_index" : "test",
  "_type" : "_doc",
  "_id" : "1567",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 29,
  "_primary_term" : 8
}

可以在返回值中看到_seq_no_primary_term
Elasticsearch跟踪要更改其存储的每个文档的最后一个操作的序号和primary term,可以通过get api来获取_seq_no和_primary_term的值,示例如:

curl -XGET "http://127.0.0.1:9200/test/_doc/1567?pretty"
{
  "_index" : "test",
  "_type" : "_doc",
  "_id" : "1567",
  "_version" : 1,
  "_seq_no" : 29,
  "_primary_term" : 8,
  "found" : true,
  "_source" : {
    "product" : "r2d2",
    "details" : "A resourceful astromech droid"
  }
}

通过序列号和primary term可以标识唯一性,通过记录返回的序列号和primary term,你可以确保只在检索后没有对文档进行其他更改的情况下更改文档,可以在index api和delete api中通过参数if_seq_no和if_primary_term来进行设置。
如果值不对,那么操作将失败,如:

curl -XPUT "http://127.0.0.1:9200/test/_doc/1567?if_seq_no=20&if_primary_term=8&pretty" -H "Content-Type:application/json" -d'
{
    "product" : "r2d2",
    "details" : "A resourceful astromech droid",
    "tags": ["droid"]
}'

返回值为:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "version_conflict_engine_exception",
        "reason" : "[1567]: version conflict, required seqNo [20], primary term [8]. current document has seqNo [29] and primary term [8]",
        "index_uuid" : "sNvURoEgQX-a2VLHwJt59Q",
        "shard" : "0",
        "index" : "test"
      }
    ],
    "type" : "version_conflict_engine_exception",
    "reason" : "[1567]: version conflict, required seqNo [20], primary term [8]. current document has seqNo [29] and primary term [8]",
    "index_uuid" : "sNvURoEgQX-a2VLHwJt59Q",
    "shard" : "0",
    "index" : "test"
  },
  "status" : 409
}

例如,下面的索引调用将确保向文档添加一个标签,而不会丢失对描述的任何潜在更改,或由另一个API添加另一个标签:

curl -XPUT "http://127.0.0.1:9200/test/_doc/1567?if_seq_no=29&if_primary_term=8&pretty" -H "Content-Type:application/json" -d'
{
    "product" : "r2d2",
    "details" : "A resourceful astromech droid",
    "tags": ["droid"]
}'

返回值为:

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

此时,_seq_no为30。
也可以关注我的公众号:程序之声
图片
关注公众号,领取更多资源

本文为博主原创文章,未经博主允许不得转载。

评论

发表评论