问:乐观并发控制-版本号形式的锁,在更新数据的时候是否会阻塞?
答:不会阻塞。类似于 CAS算法 中ABA问题的解决方案。
业务场景:想象一下我们使用Elasticsearch存储大量在线商店的库存信息。每当销售一个商品,Elasticsearch中的库存就要减一。想象两个同时运行的web进程,两者同时处理一件商品的订单时,并发情况下会造成“幻读”,并且变化越频繁,越容易丢失我们的修改:
ElasticSearch内部如何基于_version进行乐观锁并发控制?
1._version元数据
1.1 向指定index存入数据:
1 2 3 4 5 6 7 8 |
|
1.2 返回信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
第一次创建一个document的时候 ,它内部的版本号就是1;此后,每次对这个document执行修改或者删除操作,都会对这个_version版本号自动加1;
1.3 多次修改后的查询语句及结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
1.4 执行删除当前document的语句已返回结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
由上述返回结果可以发现,在执行 DELETE student/student/5 之后,返回的处理结果中存在 : "result" : "deleted" (证明执行的是删除操作) 、 "_version" : 11 (证明当前document已经执行了11次)。此时可以从侧面证明,ElasticSearch在删除某一条document数据时,不是立即物理删除掉的。因为它的一些版本号等信息还是保留着的。先删除一条document,再重新创建这条document,其实会在delete version基础之上,再把version号加1.
elasticsearch内部的多线程异步并发修改时是基于自己的_version版本号进行乐观锁并发控制的。
2.基于external version进行乐观锁并发控制
es提供了一个feature,就是说,你可以不用它提供的内部_version版本号来进行并发控制,可以基于你自己维护的一个版本号来进行并发控制。举个列子,假如你的数据在mysql里也有一份,然后你的应用系统本身就维护了一个版本号,不管是什么自己生成的还是程序控制的。这个时候,你进行乐观锁并发控制的时候,可能并不是想要用es内部的_version来进行控制,而是用你自己维护的那个version来进行控制。
1 2 |
|
version_type=external唯一的区别在于:_version,只有当你提供的version与es中的_version一模一样的时候,才可以进行修改,只要不一样,就报错;当version_type=external的时候,只有当你提供的version比es中的_version大的时候,才能完成修改。
1 2 3 |
|