如何在 Laravel 中使用锁
简单
DB::beginTransaction(); // 开启事务
$good = \App\Models\Good::sharedLock()->first(); //共享锁 s锁 读锁 (名字真多...)
// $good = \App\Models\Good::lockForUpdate()->first(); //排他锁 x锁 写锁...
DB::commit();
事务与锁
用锁需要先开启事务, 事务提交,会自动解锁。
实例说明
超卖
这个代码多人访问肯定会出现超卖的。
(如果这个代码用共享锁 不但不能解决问题,还会造成死锁)
测试
ab -n 6 -c 3 http://mask.ymindex.test/api/test
(978
出现多次,那么到0
的时候,也会出现多次,导致超卖)
使用排他锁解决超卖
共享和排他
共享: 我可以读
写
加锁
,别人可以 读
加锁
。
排他: 只有我 才 可以 读
写
加锁
,也就是说,必须要等我提交事务,其他的才可以操作。
行锁: 锁只对一行生效,比如 id=1
的那行
表锁: 锁对整个表都生效
死锁: 互相依赖,比如:多个锁住同一 行/表 数据。
如: 两个共享锁
我要修改: 你告诉我你锁了,等我("我"指的是你)先修改完。
你要修改: 我也锁了,等我(指我)先修改完。
我要修改: 你告诉我你锁了,等我(指你)先修改完。
...... 一万年后
Laravel事务解决: DB::transaction(function () {}, 5);
5是死锁时重复执行的次数 (详见文档)
.....
排他问题
会影响访问,你想,在锁期间,别人连商品点击来都看不了 (要等释放锁)。
所以我选择redis
的 lpop
。
if(! Redis::LPOP('stock'))
return 库存不足;
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 3年前 自动加精
又听别的大佬说不需要在事务中手动使用事务锁,我自己之前也是这么用的,搞迷糊了,反正没超卖.
lockForUpdate()有点意思,不过我一般都是用redis解决并发超卖的问题,事务这个东西目的保证业务数据正确,但是放到并发下,机器cpu会爆炸
知道乐观锁吗
我写在事务里sleep(20) ,然后再在另外一个请求里 可读可写,这个加锁感觉没有生效,。,。,。
@wenyu 乐观锁 悲观锁 不是对应的 共享锁和排它锁吗?还是说是新的锁?
lpop解决超卖是商品上架的时候设置100库存,就往该商品库存队列里塞100个元素吗?
我使用事务,前端不知道是不是没用帷幕点太快,自增 ID 冲突了,速来参考。