ES入门与核心原理(六)Elasticsearch并发冲突解决:乐观锁vs悲观锁

ES入门与核心原理(六)Elasticsearch并发冲突解决:乐观锁vs悲观锁

1. 并发冲突

多个线程去同时访问es中的一份数据,然后各自去修改之后更新到es,由于线程的先后顺序不同,可能会导致后续的修改覆盖掉之前的修改,显然一些场景下我们是不允许发生这种并发冲突的问题,例如电商商品库存的修改等。

如图所示,当两个用户同时下单购买奶粉时,两个线程同时去读取奶粉当前的库存,读到的库存数量都为100,此时线程A和B同时扣减库存1,当两个用户下完单时,奶粉剩余的总的库存是99,实际应该是98,由于没有加锁控制并发访问导致库存数量不准。

2. 乐观锁


商品奶粉库存100件。
乐观锁状态下是不加锁的,每个线程都可以任意操作。
此时库存为 100
当用户A购买商品后 库存-1,此时商品库存为99。这个时候用户B也提交了订单,只是用户B线程携带的数据库存为100件。乐观锁状态下,用户B会去校验 ES 中的的这条数据版本号和自身的是否一致,如果不一致,则不会提交,会重新去 ES 中获取最新的数据 99 件,再次减一,变为 98。再执行上述流程就可以写入。

优点:并发能力很高,不给数据加锁,大量线程并发操作

缺点:每次更新的时候,都要先对比版本号,然后可能需要重新加载数据,再次修改,再写;这个过程可能重复好几次

3. 悲观锁


每次去拿数据的时候都认为别⼈会修改,所以每次在拿数据的时候都会上锁,这样别⼈想拿这个数据就会阻塞,直到它拿到锁。传统的关系型数据库⾥边就⽤到了很多这种锁机制,⽐如⾏锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

常见于关系型数据库,比如mysql
商品库存100件。
当用户A读取奶粉数据的时候,会同时给数据库这一行加锁,而当用户B也读取奶粉数据的时候,这个时候会被卡出处于等待状态。
只有当用户A购买商品后 库存-1 ,才会释放锁。此时用户B突然就可以动弹了,这个时候获取到的商品库存为 99 件,当用户B购买商品后,库存变为 98。

悲观锁的控制方案就是在任何情况下,都上锁,上锁之后只有一个线程可以操作这条数据了。
当然在不同的场景下上的锁也不同,例如:表级锁、行级锁、读锁、写锁。

优点:方便,直接加锁,对程序来说透明,不需要做额外的操作

缺点:并发能力很低,同一时间只能有一条线程操作数据

4. Elasticsearch内部如何基于_version进行乐观锁并发控制

_version元数据

PUT my_index001/_doc/4
{
  "name":"奶粉",
  "dec":"少年奶粉",
  "price":250,
  "producer":"少年奶粉producer",
  "tags":["少年","补钙"]
}

{
  "_index" : "my_index001",
  "_type" : "_doc",
  "_id" : "4",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 23,
  "_primary_term" : 1
}

第一次创建一个document的时候,它的_version内部版本号就是1;以后,每次对这个document执行修改或者删除操作,都会对这个_version版本号自动加1;哪怕是删除,也会对这条数据的版本号加1

DELETE my_index001/_doc/4

{
  "_index" : "my_index001",
  "_type" : "_doc",
  "_id" : "4",
  "_version" : 2,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 24,
  "_primary_term" : 1
}

我们会发现,在删除一个document之后,可以从一个侧面证明,它不是立即物理删除掉的,因为它的一些版本号等信息还是保留着的。先删除一条document,再重新创建这条document,其实会在delete version基础之上,再把version号加1

PUT my_index001/_doc/4
{
  "name":"奶粉",
  "dec":"少年奶粉",
  "price":250,
  "producer":"少年奶粉producer",
  "tags":["少年","补钙"]
}

{
  "_index" : "my_index001",
  "_type" : "_doc",
  "_id" : "4",
  "_version" : 4,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 28,
  "_primary_term" : 1
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值