1、Elasticsearch并发冲突问题

对于一般的ES操作流程是:
1、先get document数据,比如获取到商品数据,将数据显示到网页上,同时在内存中缓存该documentd的数据
2、当网页发生了购买后,直接基于内存中的数据,进行计算和操作
3、将计算后的结果写回ES中

下面描述一下场景
比如在电商场景下,假设说,我们有一个程序,工作流程如下:
1、读取商品的信息
2、用户下单购买
3、更新商品信息(主要是将库存减1)
我们假设程序是多线程的,所以说可能有多个线程并发的去执行上述的3个步骤流程

将上述场景具体到某个商品的库存修改的时候,假设一个牙膏的库存是100件,现在同时有两个人都过来读取了牙膏的数据,然后下单购买了这管牙膏,此时两个线程并发执行,同时在进行商品库存的修改。

图片描述

如图所示,在正常的情况下,我们期望线程A将库存-1,设置为99件;然后线程B接着这个99件,将库存-1,变为98件,然后写入到ES中。
但是总有一个线程是先到的,假设就是线程A,此时线程A就会先将牙膏的库存设置为99件,然后线程B再次将牙膏的库存设置为99件,结果很显然就不是我们想要的。

上述的这个流程,其实就是ES中的并发冲突问题,会导致数据不准确。

2、悲观锁与乐观锁两种并发控制方案

这里先附上中华石衫老师画的手工图
图片描述

下面简单做一下描述和概括
悲观锁:所谓悲观锁就是在任何情况下都上锁,上锁之后,就只有一个线程可以操作这一条数据,其它线程只能等待,当然在不同的场景下,上的锁会有所不同,可以是行级锁,表级锁,读锁,写锁。通俗的来讲,加了悲观锁的话,对数据操作的时候就相当于是单线程的了。
乐观锁:其实所谓的乐观锁,根本就没有加锁,只是多了一标识字段,这个字段可以是一个整数类型的,也可以是时间类型的。主要的作用就是在每次修改数据的时候会做一层判断,判断数据是否已经被修改过了,如果已经被修改了,那么就会重新获取数据,在修改,这个过程不断进行知道数据修改成功。

下面比较一下两种锁的优缺点
1、对于悲观锁,它使用起来很方便,直接加锁就可以了,对于应用程序来说,它是透明的,不需要做额外的操作。但是每次都需要获取到锁之后才能对数据进行修改,也就是同一时间只能有一个线程能够进行操作,并发能力很低
2、对于乐观锁,它根本就没有加锁,所以并发能力很高。但是每次更新数据的时候都需要对标识字段做一个判断,这个过程可能要重复很多遍。而且是需要应用程序做处理的。

3、Elasticseach基于_version进行乐观锁的并发控制

对于ES来说,它是采用乐观锁,对应的乐观锁的标识字段是_version,是一个整数类型,一开始创建document时,_version是等于1的,之后对document每修改一次,_version版本号就会自动加1。


郑国
301 声望88 粉丝