关于面试:答面试官问如何防超卖有几种实现方式

场景

第一种办法 乐观锁

乐观并发管制(又名“乐观锁”,Pessimistic Concurrency Control,缩写“PCC”)是一种并发管制的办法。它能够阻止一个事务以影响其余用户的形式来批改数据。如果一个事务执行的操作读某行数据利用了锁,那只有当这个事务把锁开释,其余事务才可能执行与该锁抵触的操作。

乐观并发管制次要用于数据争用强烈的环境,以及产生并发抵触时应用锁爱护数据的老本要低于回滚事务的老本的环境中。

简而言之,乐观锁次要用于爱护数据的完整性。当多个事务并发执行时,某个事务对数据利用了锁,则其余事务只能等该事务执行完了,能力进行对该数据进行批改操作。


update goods set num = num - 1 WHERE id = 1001 and num > 0

假如当初商品只剩下一件了,此时数据库中 num = 1;

但有100个线程同时读取到了这个 num = 1,所以100个线程都开始减库存了。

但你会最终会察觉,其实只有一个线程减库存胜利,其余99个线程全副失败。

须要留神的是,FOR UPDATE失效须要同时满足两个条件时才失效:

  • 数据库的引擎为 innoDB
  • 操作位于事务块中(BEGIN/COMMIT)

乐观锁采纳的是「先获取锁再拜访」的策略,来保障数据的平安。然而加锁策略,依赖数据库实现,会减少数据库的累赘,且会减少死锁的产生几率。此外,对于不会发生变化的只读数据,加锁只会减少额定不必要的累赘。在理论的实际中,对于并发很高的场景并不会应用乐观锁,因为当一个事务锁住了数据,那么其余事务都会产生阻塞,会导致大量的事务产生积压拖垮整个零碎。

第二种方法 乐观锁


select version from goods WHERE id= 1001

update goods set num = num - 1, version = version + 1 WHERE id= 1001 AND num > 0 AND version = @version(下面查到的version);

这种形式采纳了版本号的形式,其实也就是CAS的原理。

假如此时version = 100, num = 1; 100个线程进入到了这里,同时他们select进去版本号都是version = 100。

而后间接update的时候,只有其中一个先update了,同时更新了版本号。

那么其余99个在更新的时候,会察觉version并不等于上次select的version,就阐明version被其余线程批改过了。那么我就放弃这次update

第三种办法 redis音讯队列

在秒杀的状况下,高频率的去读写数据库,会重大造成性能问题。所以必须借助其余服务, 利用redis的单线程预减库存。比方商品有100件。那么我在redis存储一个k,v。例如

每一个用户线程进来,key值就减1,等减到0的时候,全副回绝剩下的申请。

那么也就是只有100个线程会进入到后续操作。所以肯定不会呈现超卖的景象。

第四种方法 redis分布式锁


$expire = 10;//有效期10秒

$key = 'lock';//key

$value = time() + $expire;//锁的值 = Unix工夫戳 + 锁的有效期

$lock = $redis->setnx($key, $value);

//判断是否上锁胜利,胜利则执行下步操作

if(!empty($lock))

{

//下单逻辑...

}

第四种办法,能够参考本书的这个章节:Redis实现分布式锁

转自我的电子书

https://www.kancloud.cn/marti…

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据