首页 > 其他分享 >ElasticSearch 数据并发冲突处理

ElasticSearch 数据并发冲突处理

时间:2024-05-13 17:57:15浏览次数:12  
标签:term 版本号 并发 version 文档 冲突 版本 ElasticSearch Elasticsearch

一.概述

  Elasticsearch使用文档版本来控制文档的并发更新,并用于解决冲突。Elasticsearch从写入到检索的时间间隔是由刷新频率refresh_interval设定的,该值可以更新,但默认最快是1s,也就是这1秒之内如果同一条数据(文档的新版本必须复制到群集中的其他节点。 Elasticsearch 也是异步和并发的),有多次更新或删除操作,则可能会引起文档版本冲突。

  每一个文档数据都有一个_version,代表文档的版本号。当我们在Elasticsearch中创建一个新文档时,它会为该文档分配一个_version:1。当我们后续对该文档进行任何操作(如更新、索引或删除)时,_version都会增加1,如下所示:

{
  "_index" : "my_index_1006",
  "_type" : "_doc",
  "_id" : "2",
  "_version" : 3,
  "_seq_no" : 6,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "B",
    "sales" : 20,
    "visitors" : 20
  }
}

  这里_version值为3,代表更新该文档有二次,Elasticsearch使用_version来鉴别文档是否已更改。

  当频繁更新文档时,有时会出现http 409状态,version_conflict_engine_exception异常,这就是版本冲突。Elasticsearch是不允许旧版本文档覆盖新版本文档数据。

  Elasticsearch是采集乐观锁并发控制,Elasticsearch乐观锁实质上没有给数据加锁,而是基于文档版本实现的,每次更新或删除数据的时候都需要对比版本号。

 

二.解决和避免文档版本冲突

  2.1 使用external对版本号控制    

    Elasticsearch提供了多种版本控制策略,其中之一便是利用external来对版本号进行外部控制。这种机制允许在Elasticsearch外部(如数据库)维护版本号的值,以实现对索引操作的精细控制。要启用此功能,需要将version_type设置为external。

    在external模式下,Elasticsearch相当于将版本控制的责任委托给了外部数据库或其他第三方库,它们负责生成和管理文档的版本号。这种方式可以看作一种放权操作,它让数据源对其数据在Elasticsearch中的版本有更多的控制权。

    例如mysql数据要同步到es中, 可以在mysql中创建一个字段来管理es版本号,如取值为:修改数据的毫秒的时间戳或者数字值递增。

    当使用external版本类型时,Elasticsearch在处理索引请求时会对比传入文档的版本号和已存储文档的版本号。如果传入的版本号大于已存储的,就表明这是一个新版本的文档,Elasticsearch则会执行索引操作并更新文档的版本号。然而,如果传入的版本号小于或等于已有版本号,这就意味着可能存在并发修改的问题,Elasticsearch会认为发生了版本冲突,索引操作将被拒绝,出现version_conflict_engine_exception异常和http 409状态。

    使用时间戳做为版本号示例如下:

PUT my_index_1006/_doc/3?version=1234567891235&version_type=external
{
   "sales":50,
   "visitors":10,
   "name":"A"
}

    利用external控制版本号的优势在于,它能确保Elasticsearch中的数据始终是最新的,因为任何过期的修改都会因版本冲突而被拒绝。此外,借助external版本控制,可以更有效地解决并发修改带来的版本冲突问题,从而保证数据的一致性和完整性。

     

  2.2使用if_seq_no和if_primary_term避免版本冲突

    Elasticsearch提供了一种更精细的版本控制机制——通过if_seq_no和if_primary_term参数来对文档的版本进行唯一标识,从而避免并发操作引起的冲突。

    在执行索引写入操作时,Elasticsearch会检查传入的if_seq_no和if_primary_term是否与最后一次修改文档的序列号(seq no)和主要项(primary term)匹配。这两个参数共同提供了一种强大的控制机制,确保只有当所提供的版本信息与文档的最新状态一致时,才会执行写入操作。

    如果if_seq_no和if_primary_term的值与当前文档状态不匹配,Elasticsearch会认为发生了版本冲突。在这种情况下,系统会返回一条“VersionConflictException”的报错信息,同时伴随一个409的HTTP状态码,表明请求的操作由于版本冲突而未能成功执行。

    更新或删除前,先用get根据文档id,获取到该文档的if_seq_no和if_primary_term值,如下所示:

#发送请求
get my_index_1006/_doc/3

#返回结果获取到_seq_no和_primary_term { "_index" : "my_index_1006", "_type" : "_doc", "_id" : "3", "_version" : 1234567891235, "_seq_no" : 16, "_primary_term" : 1, "found" : true, "_source" : { "sales" : 50, "visitors" : 10, "name" : "A" } }

    执行更新操作

PUT my_index_1006/_doc/3?if_seq_no=16&if_primary_term=1
{
   "sales":70,
   "visitors":10,
   "name":"A"
}

    

  2.3批量更新或删除使用proceed忽略冲突

    在_update_by_query和_delete_by_query命令请求中,加入conflicts=proceed,实际上是告诉进程忽略冲突并继续更新其他文档。经过该操作,代码运行不会报409错误了,但依然会有版本冲突。不过,在某些企业级场景下,该操作是有效的。

   示例如下所示:

post /hqbuy_stock/_update_by_query?conflicts=proceed
{
  "query": {
    "term": {
      "Id": {
        "value": "541607807996132"
      }
    }
  },
   "script": {
      "source": "ctx._source['PartNo']='1NT01L-7942';"
    }
}

#返回结果中,version_conflicts代表冲突数量
{
  "took" : 7461,
  "timed_out" : false,
  "total" : 1,
  "updated" : 1,
  "deleted" : 0,
  "batches" : 1,
  "version_conflicts" : 0,
  "noops" : 0,
  "retries" : {
    "bulk" : 0,
    "search" : 0
  },
  "throttled_millis" : 0,
  "requests_per_second" : -1.0,
  "throttled_until_millis" : 0,
  "failures" : [ ]
}

 

考参文献:  官方乐观并发控制文档

      一本书讲透Elasticsearch

  

标签:term,版本号,并发,version,文档,冲突,版本,ElasticSearch,Elasticsearch
From: https://www.cnblogs.com/MrHSR/p/18186799

相关文章

  • 安装 elasticsearch & kibana (docker )
    1.elasticsearchdockerrun-e"ES_JAVA_OPTS=-Xms256m-Xmx256m"\--nameelasticsearch-p9200:9200-p9300:9300\-e"discovery.type=single-node"\-v/usr/share/elasticsearch/config:/usr/share/elasticsearch/config\-delasticsea......
  • openGauss 管理并发写入操作
    管理并发写入操作事务隔离说明写入和读写操作并发写入事务的潜在死锁情况并发写入示例......
  • Entity Framework Core中的并发处理
    1.常见的并发处理策略要了解如何处理并发,就要知道并发的一般处理策略悲观并发策略悲观并发策略,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守悲观的态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观并发策略大多数......
  • go高并发之路——缓存穿透、缓存雪崩
    缓存击穿、缓存穿透、缓存雪崩是使用Redis的三个经典问题,上篇文章讲了缓存击穿,今天就讲下剩下的两个问题。一、缓存穿透定义:缓存穿透是指查询一个根本不存在的数据,缓存层和DB层都不会命中。这样缓存永远不会生效,这些请求最终都会访问数据库。引起DB的压力瞬间变大,导致服务不可用......
  • Java-线程-并发解决方案
    0.背景在[Java-线程-并发]这篇文章中,我们引入了并发场景下的一些问题,并在末尾给出了几种常见的解决方案。1.方案1.1synchronizedsynchronized是Java中的一个关键字,用于提供同步机制,保证多线程环境下对共享资源的安全访问。通过使用synchronized,Java虚拟机(JVM)保证同一时......
  • Java-线程-并发问题和ConcurrentHashMap
    0.背景在经典八股文中,我们会背:啊,hashmap是线程不安全的,concurrentHashMap是线程安全的。然后呢,又背:啊,为啥ConcurrentHashMap是安全的,因为加锁了。好好好,接着八股:啊,啥啥分段锁。本文,结合实际例子来进行分析,这他妈的到底是在叭叭啥。一切,从一个Hashmap的demo谈起。pu......
  • 阿里2面:你们部署多少节点?1000W并发,当如何部署?
    阿里2面:你们部署多少节点?1000W并发,当如何部署? 文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技......
  • Java面试题:Spring Bean线程安全?别担心,只要你不写并发代码就好了!
    Spring中的Bean是否线程安全取决于Bean的作用域(scope)。Spring提供了几种不同的Scope,其中包括Singleton、Prototype、Request、Session、GlobalSession等。 SingletonScope(单例模式)默认情况下,SpringBean是SingletonScope,这意味着在整个应用程序上下文中只有一个实例。......
  • Springboot单机多副本运行,解决端口冲突
    一、代码方式(修改配置类)@BeanpublicWebServerFactoryCustomizer<ConfigurableWebServerFactory>MyCustomizer(){returnnewWebServerFactoryCustomizer<ConfigurableWebServerFactory>(){@Overridepublicvoidcustomize(ConfigurableWebSer......
  • Elasticsearch 自定义评分
    一.概述在前几章中,讲到了如何分词,以及分词的种类。分词后在进行全文检索时,返回结果如何确定用户真正想看到的, 那数据结果如何排序呢?比如在电商中:搜索一个商品关键词,默认是综合排序,商品如何顺序是经过一定的算法策略,也是为了提高用户的体验。Elasticsearch使用评分算......