ES update接口版本冲突问题的论述
基本概念介绍众所周知,es数据的版本控制是通过乐观锁来实现的。es的每个document中都维护了一个_version字段,这个字段表示了这个文档的版本号,文档刚创建之时,_version=1,后续对该文档的任何增删改操作都会使_version递增(注意删除文档也是会递增的!)。假设一个document的_version=4,我们提交了一个update请求去更新该文档,请求后缀带了?verso..
基本概念介绍
众所周知,es数据的版本控制是通过乐观锁来实现的。es的每个document中都维护了一个_version字段,这个字段表示了这个文档的版本号,文档刚创建之时,_version=1,后续对该文档的任何增删改操作都会使_version递增(注意删除文档也是会递增的!)。
假设一个document的_version=4,我们提交了一个update请求去更新该文档,请求后缀带了?verson=2 来指定版本号。由于指定的版本号2与文档版本号4不匹配,更新请求将会因为版本冲突导致操作失败。如果我们将请求指定的版本号改为4或者不指定版本号,更新就可以成功。这就是es的乐观锁。
问题引入
下面是本文的重点论述内容:
上面提到过,update不指定版本号,就不会有版本冲突的问题。其实这只是在非并发的场景下成立。如果有多个请求同一时间对同一个文档执行不指定版本号的update请求,那么还是很有可能报版本冲突的错误的。这是为什么呢?
首先我们需要了解update请求的实现步骤:
1、客户端发送update请求
2、根据document id查询es中已有的文档内容
3、从查询内容中获取版本号,将请求中的更新内容与查询到的文档合并成一个全量文档
4、将全量文档PUT 到es中,并且指定版本号为查询到的版本号
5、如果PUT请求中的的版本号与已有文档的版本号匹配,将文档内容替换,否则报版本冲突,操作失败。
从第4步骤可知,update操作的内部实际上还是指定了版本号的。因此,当多个请求同一时间对同一个文档执行update操作时,他们在步骤3中获取到的_version可能是一样的,等到第5步的时候,可能已经有其它请求先一步更新了文档,_version也已经被更新了,这样请求就会报版本冲突。
解决
如果要解决上述问题,可以在请求中添加retry_on_conflict参数,它代表更新版本冲突后的重试次数。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)