标签:自动 方便 相同 版本号 inf class delete 基础 res
举个例子,比如是电商场景下,假设说,我们有个程序,工作的流程是这样子的:
我们比如咱们的程序就是多线程的,所以可能有多个线程并发的去执行上述的3步骤流程
有一个牙膏,库存100件,现在,同时有两个人都过来读取了牙育的数据,然后下单购买了这管牙膏,此时两个线程并发的服务于两个人,同时在进行商品库存数据的修改
总有一个线程是先到的,假设就是线程A ,此时线程A就会先将牙育的库存设置为99件,然后线程B再次将牙育的库存设置为99件,此时结果就已经错了
正确的情况下,我们期望的,应该是说,线程A将库存-1,设置为99件;然后线程B接着这个99件,将库存-1,变为98件,然后设置到ES中。最终ES中应该库存是98件才对啊.
普通的ES操作流程:
上面说的这个流程和过程,其实就是ES中的并发冲突问题,会导致数据不准确:
优缺点:
悲观锁并发控制方案,就是在各种情况下,都上锁。上锁之后,就只有一个线程可以操作这一条数据了,当然,不同的场景下,上的敏不同,行级锁,表级锁,读锁,写锁。
乐观锁是不加锁的, ,每个线程都可以任意操作
线程B去判断,当前数据的版本号,version=1,与es中的数据的版本号, version=2,是否相同?明显是不同的。版本号不同,说明数据已经被其他人修改过了。此时用户B不会用99去更新。而是重新去es中读取最新的数据版本,99件,再次减 1,变为98件,再执行上述流程,就可以写入
示例数据:
PUT /test_index/test_type/6 { "test_field": "test test" }
{ "_index": "test_index", "_type": "test_type", "_id": "6", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "created": true }
第一次创建一个document的时候,它的_version内部版本号就是1;以后,每次对这个document执行修改或者删除操作,都会对这个_version版本号自动加1;哪怕是删除,也会对这条数据的版本号加1
{ "found": true, "_index": "test_index", "_type": "test_type", "_id": "6", "_version": 4, "result": "deleted", "_shards": { "total": 2, "successful": 1, "failed": 0 } }
我们会发现,在删除一个document之后,可以从一个侧面证明,它不是立即物理删除掉的,因为它的一些版本号等信息还是保留着的。先删除一条document,再重新创建这条document,其实会在delete version基础之上,再把version号加1
ES后台同步:知识点: es的后台,很多的这种类似于replica同步请求,都是多线程异步的,也就是说,多个修改请求之间,是乱序的,没有顺序的,可能后修改的先到,先修改的后到
假设es内部没有乐观锁并发控制机制:
es内部的多线程异步并发修改时,是基于自己的_version版本号进行,在后修改先到时,那么field-test3, version=2,先修改后到时,先修改的field=test2 , version-1 ,此时会比较一下version号,是否相等,如果不相等的话,那么就直接将 field-test2这条数据给扔掉,就不需要了,这样的话,结果就会保持为一个正确的状态, field-test3
Elasticsearch由浅入深(四)ES并发冲突、悲观锁与乐观锁、_version乐观锁并发
标签:自动 方便 相同 版本号 inf class delete 基础 res
原文地址:https://www.cnblogs.com/wyt007/p/11382028.html