交易扣款乐观锁使用
比如说余额更新,防止重复
悲观锁性能很差,我目前用的是乐观锁,但是用的是 `User::where (‘id’, $user->id)->where (‘version’, $user->version)->update ([]);`
这种方式感觉不是很优雅,看手册,发现有一个原子锁,`Cache::lock ()` 这个方案你们觉得怎么样?
回答处理
- 放一段一直在用的代码仅供参考,这段代码是所有加减款都必须经过这个方法,所以只在加入这个 lock,下面的代码类似于乐观锁,利用缓存键加入一个钱包 ID,只会在这个钱包 ID 业务下 lock,其它钱包 ID 是另一个 lock 键锁互不影响
- if 判断不那么优雅,按照文档说法应该放到 catch 里,但没啥问题,我也不想去改这个逻辑了。又不是不能用(图先欠着)
$out_purse = null;
$out_lock = Cache::lock('EBank@_transfer:' . $out_purse_id);
try {
$out_purse = $out_lock->block(50, function () use ($out_purse_id, $amount) {
$var = FundPurse::where(['id' => $out_purse_id, 'status' => 1])->where('balance', '>=', $amount)->decrement('balance', $amount);
// 未修改返回修改行数为0
if (!$var) {
return false;
}
return FundPurse::find($out_purse_id);
});
optional($out_lock)->release();
} catch (LockTimeoutException $e) {
} finally {
optional($out_lock)->release();
}
if ($out_purse === null) {
abort(422, '转出钱包查询超时');
}
if ($out_purse === false) {
abort(422, '转出钱包扣款失败,余额不足或账户被禁用');
}
转自:https://learnku.com/laravel/t/61510