Elasticsearch中的序列号与版本号

我正在阅读elasticsearch-7.4的概念,并且了解了两个领域。 _seq_no_version

根据文档:

版本

Returns a version for each search hit.

序列号和主要术语

Returns the sequence number and primary term of the last modification to each search hit.

但是并没有清除与文档何时它们将不同或相同的任何相关内容。

我创建了一个索引test

PUT /test/_doc/_mapping
{
  "properties": {
    "total_price" : {
      "type": "integer"
    },"final_price": {
      "type": "integer"
    },"base_price": {
      "enabled": false
    }
  }
}

我正在使用PUT API更新整个文档。

PUT /test/_doc/2
{
  "total_price": 10,"final_price": 10,"base_price": 10
}

在这种情况下, _seq_no和_version都在增加

使用UPDATE API进行部分更新时,

POST /test/_doc/2/_update
{
    "doc" : {
        "base_price" : 10000
    }
}

在这种情况下,_seq_no和_version都在增加

因此,当只有一个字段发生变化而另一字段没有变化时,我无法找到情况。
这两个字段何时会不同?

dongjian_011 回答:Elasticsearch中的序列号与版本号

序列号已在ES 6.0.0中引入。在该版本发布之前,blog article中对它们进行了很好的解释。

但总而言之,

  • version是一个序列号,用于计算文档更新的时间
  • _seq_no是一个序列号,用于计算索引上发生的操作次数

因此,如果您创建第二个文档,您会发现version_seq_no将有所不同。

让我们创建三个文档:

POST test/_doc/_bulk
{"index": {}}
{"test": 1}
{"index": {}}
{"test": 2}
{"index": {}}
{"test": 3}

在响应中,您将在下面获得有效负载。

{
  "took" : 166,"errors" : false,"items" : [
    {
      "index" : {
        "_index" : "test","_type" : "_doc","_id" : "d2zbSW4BJvP7VWZfYMwQ","_version" : 1,"result" : "created","_shards" : {
          "total" : 2,"successful" : 1,"failed" : 0
        },"_seq_no" : 0,"_primary_term" : 1,"status" : 201
      }
    },{
      "index" : {
        "_index" : "test","_id" : "eGzbSW4BJvP7VWZfYMwQ","_seq_no" : 1,"_id" : "eWzbSW4BJvP7VWZfYMwQ","_seq_no" : 2,"status" : 201
      }
    }
  ]
}

如您所见:

  • 对于所有文档,版本均为1
  • 对于文档1,_seq_no为0(第一次索引操作)
  • 对于文档2,_seq_no为1(第二索引操作)
  • 对于文档3,_seq_no为2(第三索引操作)
,

Elasticsearch文档是不可变的

Elasticsearch文档是不可变的,这意味着无论您何时更新文档,都将创建该文档的新版本,无论您是否使用PUT(更新整个文档)或POST(更新文档的某些部分)。

每个新创建的文档将获得一个新的递增的版本,该字段由_version字段标识:

{
    "_index": "movies","_type": "_doc","_id": "109487","_version": 14,"result": "updated","_shards": {
        "total": 2,"successful": 1,"failed": 0
    },"_seq_no": 17,"_primary_term": 7
}

博客网站

假设您有一个博客网站,并且有 2 个用户同时点击了ID为 1 的同一博客帖子 : GET https://myblog.com/posts/1

回到Elasticsearchpost文档中有一个名为view_count的字段,该字段存储了查看的总数(查看过该帖子的次数 )。

要递增view_count,您必须发送一个GET请求以读取当前值:

GET /posts/_doc/1
{
    "_index": "movies","_version": 12,"_seq_no": 15,"_primary_term": 7,"found": true,"_source": {
        "post": "Lorem ipsum ...","title": "My title","published_at": "2020-01-01","view_count": 10
    }
}

然后,通过将返回值(从view_count开始)增加 1 ,来更新帖子ID 1 GET

PUT /posts/_doc/1/_update
{
    "doc": {
        "view_count": 11
    }
}

这里有问题

由于两个用户都同时访问了相同的帖子页面,因此他们将获得10的价值。

如您在此处看到的,存储了值 11 ,但这是不正确的,因为我们两次更新了文档(记住2个用户同时点击了帖子ID ),因此该值应为 12

但是为什么呢?这是因为两个用户在读取10时都获得了值view_count

那么,我们如何解决这个问题?

幸运的是,Elasticsearch使用了称为乐观并发控制 OCC )(Optimistic concurrency control - Wikipedia)的东西。

为确保需要更新最近的文档,我们将if_primary_term值与if_seq_no值一起发送(从GET请求中获取):

POST /posts/_update/1?if_primary_term=1&if_seq_no=10

就这样。

本文链接:https://www.f2er.com/3139774.html

大家都在问