Elasticsearch7.x——乐观并发控制、refresh参数

本文详细介绍了Elasticsearch中的乐观并发控制机制,以及refresh参数在控制文档更改对搜索可见性中的作用,包括不同refresh值的选择和强制刷新的情况。

1、乐观并发控制

Elasticsearch是分布式的,创建、更新或删除文档时,必须将 文档的新版本复制到集群中的其他节点。Elasticsearch也是异步和并发的,这意味着这些复制请求是并行发送的,并且可能不按顺序到 达目的地。Elasticsearch需要一种方法来确保旧版本的文档永远不 会覆盖新版本的文档。

为了确保旧版本的文档不会覆盖新版本文档,对文档执行的每个 操作都由主分片分配一个序列号,序列号随着每个操作的增加而增 加,因此新操作的序列号肯定比旧操作的序列号更高。然后, Elasticsearch可以使用这个序列号来确保新的文档版本不会被分配 了较小序列号的更改覆盖。

例如,以下索引命令将创建一个文档并为其分配初始序列号 _seq_no_primary_term ( _primary_term 和 _seq_no 都是整 数),每当主分片发生重新分配时,比如重启、Primary选举等, _primary_term会递增1:

PUT products/_doc/1
{
  "product":"r2d2",
  "details":"A resourceful astromech droid"
}

在响应中包括分配的_seq_no和_primary_term:

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

Elasticsearch 跟 踪 上 次 操 作 的 _seq_no _primary_term, 以 更改其存储的每个文档。在GET API的响应中,会在_seq_no和 _primary_term字段中返回:

GET products/_doc/1
{
  "_index" : "products",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "product" : "r2d2",
    "details" : "A resourceful astromech droid"
  }
}

搜索API可以通过设置seq_no_primary_term参数返回每个命中 文档的_seq_no和_primary_term:

GET products/_search
{
  "seq_no_primary_term":true,
  "query": {
    "match": {
      "details": "droid"
    }
  }
}
{
  "took" : 5,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "products",
        "_type" : "_doc",
        "_id" : "1",
        "_seq_no" : 0,
        "_primary_term" : 1,
        "_score" : 0.2876821,
        "_source" : {
          "product" : "r2d2",
          "details" : "A resourceful astromech droid"
        }
      }
    ]
  }
}

_seq_no和_primary_term唯一地标识一个变更。通过记下返回 的这两个值,可以确保仅在检索文档后没有对其进行其他更改的情况 下更改文档。这是通过设置索引API或删除API的if_seq_no和 if_primary_term参数来完成的。

例如,以下调用将确保向文档中添加标记tag,而不会丢失对描述 的任何潜在更改或由其他API添加其他标记:

POST products/_update/1?if_seq_no=0&if_primary_term=1
{
  "doc": {
    "tags": ["droid"]
  }
}
{
  "_index" : "products",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "_seq_no" : 1,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "product" : "r2d2",
    "details" : "A resourceful astromech droid",
    "tags" : [
      "droid"
    ]
  }
}

2、refresh参数

索引、更新、删除和批量API支持用refresh参数来控制请求所做 的更改何时对搜索可见。

允许的值如下:

  • 空或true:操作发生后立即刷新相关的主分片和副本分片(不是整个索引),以便更新的文档立即显示在搜索结果中。这个设置需要仔细考虑和验证,因为会导致性能下降(从索引和搜索的角度来看)。
  • wait_for:在返回结果之前,将等待刷新使请求所做的更改可见,这不会强 制立即刷新,而是等待刷新发生。Elasticsearch自动刷新,刷新频 率是index.refresh_interval,默认是1s。这个设置是动态的。调用 refresh API,或在响应的API上设置refresh为true都将导致刷新,请 求将返回。
  • false(默认值):不执行与刷新相关的操作。此请求所做的更改将在请求返回后的 某个时间点可见。

2.1、如何选择refresh的值

除非有充分的理由等待更改变为可见,否则始终使用 refresh=false。

如果必须使请求所做的更改与请求同步可见,当设置refresh为 true时,Elasticsearch将增加更多负载,设置为wait_for;将等待更 长时间,这需要结合实际情况决定。

2.2、强制刷新

如果当已经有index.max_refresh_listeners值定义数量(默认 为1000个)的请求在该分片上等待刷新时,该请求的行为将如同 refresh设置为true一样:它将强制刷新。这保证了当该请求返回时,其更改对搜索可见,同时防止对被阻塞的请求使用未经检查的资源。 如果请求由于监听器槽用完而强制刷新,则其 响应将包含"forced_refresh":true信息。

批量请求只占用它们接触的每个分片上的一个槽,不管它们修改 分片多少次。

例如,如下将请求创建文档并立即刷新索引,使其可见:

PUT /test/_doc/1?refresh
{"test":"test"}
PUT /test/_doc/2?refresh=true
{"test":"test"}

如下操作都将创建一个文档,但文档不会立即可见,请求立即返 回不会等待文档可见:

PUT /test/_doc/3
{"test":"test"}
PUT /test/_doc/4?refresh=fase
{"test":"test"}

如下操作将创建一个文档,并等待其在搜索时变为可见:

PUT /test/_doc/5?refresh=wait_for
{"test":"test"}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值