聊聊ElasticeSearch并发写的乐观锁机制

聊聊,elasticesearch,并发,乐观,机制 · 浏览次数 : 332

小编点评

**ES的多客户端并发更新是基于乐观并发控制的,通过版本号机制来实现冲突检测。** **乐观锁的版本号机制** 乐观锁是一种并发控制技术,它允许多个线程访问共享资源时,确保资源被正确处理。在ES中,乐观锁通过版本号来实现并发控制。 **版本号的用法** 版本号是一个文档的唯一标识符,它用于区分文档的不同版本。当多个客户端想要更新文档时,它们会比较他们的版本号,如果版本号相同,就表示没有冲突。 **版本号的更新** 当客户端向ES发送更新请求时,ES会将请求传递给服务器。服务器会比较客户端提供的版本号与文档的最新版本号。如果版本号一致,表示没有冲突,操作可以继续进行。如果版本号不一致,表示发生了版本冲突,更新操作会被拒绝并抛出`VersionConflictEngineException`异常。 **版本号的原子性** 为了确保并发更新的原子性,ES会对文档的版本号进行原子性更新。这意味着在更新过程中,其他并发的更新请求会被阻塞,直到当前更新操作完成。 **版本冲突的解决** 当多个客户端在同一时间想要更新文档时,版本号就会冲突。ES提供以下机制来解决版本冲突: - 获取冲突列表:客户端在更新请求中获取冲突列表,包含所有发生冲突的版本号。 - 配置重试策略:如果版本冲突的数量超过预设的阈值,ES会配置重试策略,并尝试更新文档 multiple 次。 - 返回结果:客户端可以从服务器中获取最终更新结果,包括文档的内容、版本号等。

正文

概述

ES的多客户端并发更新是基于乐观并发控制,通过版本号机制来实现冲突检测。

关键对象

ES的老版本是用过_version字段的版本号实现乐观锁的。现在新版增加了基于_seq_no_primary_term字段,三个字段做乐观锁并发控制。

image

_version:标识文档的版本号,只有当前文档的更新,该字段才会累加;以文档为维度。

_seq_no:标识整个Index中的文档的版本号,只要Index中的文档有更新,就会累加该字段值;以Index为维度记录文档的操作顺序。

_primary_term:针对故障导致的主分片重启或主分片切换,每发生一次自增1;已分片为维度。

原先修改指定版本的请求参数是_version;目前修改指定版本的请求参数只能是

PUT user/_doc/1?if_seq_no=22&if_primary_term=2

乐观并发控制

乐观锁的操作主要就是两个步骤:

  • 第一步:冲突检测。
  • 第二步:数据更新。

参考乐观锁的版本号,JDK提供了一个AtomicStampedReference类,在CAS的基础上增加了一个Stamp(印戳或标记),使用这个印戳可以用来觉察数据是否发生变化,给数据带上了一种实效性的检验。

为什么要说到这个?网上很多资料就是一笔带过ES是通过乐观锁版本号来实现并发控制的,我就纳闷,仅仅通过版本号怎么实现的?ES的乐观锁实现就是类似AtomicStampedReference原理。其流程大致如下:

  1. 获取当前文档的最新版本号:在更新操作开始之前,Elasticsearch会获取当前文档的最新版本号。

  2. 检查版本号冲突:客户端在更新请求中提供了要更新文档的版本号,服务器会将客户端提供的版本号与实际文档的最新版本号进行比较。

  3. 如果客户端提供的版本号与实际文档的最新版本号一致,表示没有冲突,操作可以继续进行。

  4. 如果客户端提供的版本号与实际文档的最新版本号不一致,表示发生了版本冲突,更新操作会被拒绝并抛出VersionConflictEngineException异常。

  5. 原子性更新版本号:如果没有发生版本冲突,Elasticsearch会对文档的版本号进行原子性的更新。这意味着在更新过程中,其他并发的更新请求会被阻塞,直到当前更新操作完成。

  6. 更新文档内容:在版本号更新完成后,Elasticsearch会执行实际的文档更新操作,包括更新字段的值、添加或删除字段等。

这个过程就是一个典型的read-then-update的过程,ES保证原子事务。其实在并发更新下,哪怕是基于乐观锁多版本号控制,是一定要通过某种机制保证冲突检测与数据更新的原子性;并不是简单的一句多版本控制实现了乐观锁(是我自己较真了)。

翻了下GPT,如下是给出的回复。佐证了我的猜想(源码看了下,翻不动!)

image

image

image

冲突检测的解决

乐观锁出现版本冲突时,ES提供了相应的机制获取冲突

List<VersionConflict> conflicts = response.getGetResult().getConflicts();

同时还可以配置重试策略,因为一般情况下,都是可以通过重试解决的,ES中配置retry_on_confict即可。

与聊聊ElasticeSearch并发写的乐观锁机制相似的内容:

聊聊ElasticeSearch并发写的乐观锁机制

### 概述 ES的多客户端并发更新是基于乐观并发控制,通过版本号机制来实现冲突检测。 ### 关键对象 ES的老版本是用过`_version`字段的版本号实现乐观锁的。现在新版增加了基于`_seq_no`与`_primary_term`字段,三个字段做乐观锁并发控制。 ![image](https

聊聊我认为的分布式、集群实现关键点

基于常见的中间件(Mysql、ElasticSearch、Zookeeper、Kafka、Redis)等分布式集群设计的机制,自己总结了在在集群设计过程中需要考虑的通用问题。 ### 节点通信机制 主节点的增加、删除、通信机制。 ### 路由算法 即数据路由到哪个节点的策略机制。在集群内有多个节点,

京东云开发者|ElasticSearch降本增效常见的方法

Elasticsearch在db_ranking 的排名又(双叒叕)上升了一位,如图1-1所示;由此可见es在存储领域已经蔚然成风且占有非常重要的地位。随着Elasticsearch越来越受欢迎,企业花费在ES建设上的成本自然也不少。那如何减少ES的成本呢?今天我们就特地来聊聊ES降本增效的常见方法。

聊聊GLM-4-9B开源模型的微调loss计算

概述 Github官方地址:GLM-4 网上已经有很多关于微调的文章,介绍各种方式下的使用,这里不会赘述。我个人比较关心的是微调时的loss计算逻辑,这点在很多的文章都不会有相关的描述,因为大多数人都是关心如何使用之类的应用层,而不是其具体的底层逻辑,当然咱也说不清太底层的计算。 可了解其它loss

聊聊一个差点被放弃的项目以及近期的开源计划

前言 自从 StarBlog 和 SiteDirectory 之后,我还没写新的关于开源项目的系列,最近又积累了很多想法,正好写一篇博客来总结一下。 关于差点被放弃的项目,就是最近一直在做的单点认证(IdentityServerLite) IdentityServerLite 开发这个项目的起因,是

聊聊 JSON Web Token (JWT) 和 jwcrypto 的使用

哈喽大家好,我是咸鱼。 最近写的一个 Python 项目用到了 jwcrypto 这个库,这个库是专门用来处理 JWT 的,JWT 全称是 JSON Web Token ,JSON 格式的 Token。 今天就来简单入门一下 JWT。 官方介绍:https://jwt.io/introduction

聊聊MySQL是如何处理排序的

在MySQL的查询中常常会用到 order by 和 group by 这两个关键字,它们的相同点是都会对字段进行排序,那查询语句中的排序是如何实现的呢?

聊聊 Linux iowait

哈喽大家好,我是咸鱼。 我们在使用 top 命令来查看 Linux 系统整体 CPU 使用情况的时候,往往看的是下面这一列: %Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 68.0 wa, 0.0 hi, 0.0 si, 0.0 st 其中,man 手册解释 w

聊聊Mybatis框架原理

好久没有写博客了。最近工作中封装了一个类似ORM框架的东西。大概的原理就是将Excel数据初始化到本地sqlite数据库后,通过json配置文件,对数据库的数据做增删改查等操作。 其实大概的思考了下,就是半ORM框架mybatis的逻辑,只是我们自己封装的简陋蛮多。想想有现成的轮子没用,反而是自己写

聊聊Spring的工厂方法与FactoryBean

概述 工厂方法是比较常见,常用的一种设计模式。FactoryBean是Spring提供的一种Bean注入IOC容器的方式。 工厂方法 在做日常开发时,一般都会避免直接new对象,而且将new的操作丢给IOC容器,但对于第三方系统的集成,我们不太好直接丢给IOC容器,此时可以通过工厂模式, 提供一个工