你们是怎么解决资金安全问题的

比如说余额更新,防止重复

悲观锁性能很差,我目前用的是乐观锁,但是用的是User::where(‘id’, $user->id)->where(‘version’, $user->version)->update([]);
这种方式

感觉不是很优雅,看手册,发现有一个原子锁,Cache::lock() 这个方案你们觉得怎么样

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 4
yybawang

我就是用的 Cache::lock() 目前用了几年也没发现什么问题,用的docker 单个 redis 容器服务

  • 放一段一直在用的代码仅供参考,这段代码是所有加减款都必须经过这个方法,所以只在加入这个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, '转出钱包扣款失败,余额不足或账户被禁用');
              }
2年前 评论
SupeRod 2年前

@yybawang 感谢无私分享啊,我研究研究

2年前 评论

Cache驱动是Redis的话 本质就是Redis分布式锁

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!