Elasticsearch——乐观并发控制、refresh参数

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

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"}
  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值