场景
第一种办法 乐观锁
乐观并发管制 (又名“ 乐观锁”,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…