Laravel 使用RedisLock解决并发问题
作者:钓赛通
发布时间:2022-02-16
点击数:
以下是RedisLock 的服务类
namespace App\Services; use App\Admin; use App\Model\AdvocateClient; use App\Exceptions\CaseSerException; use DB; class RedisLockService { private $redis; private $timeout = 10; public function __construct(\Redis $redis) { $this->redis = $redis; } public function getLockCacheKey($key) { return "lock_{$key}"; } /** * @desc // 获取锁 * @param $key 锁ID * @param null $timeout 超时自动释放 * @return bool|int|string|null * author eRic * dateTime 2022-02-16 08:57 */ public function getLock($key, $timeout = NULL) { $timeout = $timeout ? $timeout : $this->timeout; $lockCacheKey = $this->getLockCacheKey($key); $expireAt = time() + $timeout; $isGet = (bool)$this->redis->setnx($lockCacheKey, $expireAt); if ($isGet) { return $expireAt; } while (1) { usleep(10); $time = time(); $oldExpire = $this->redis->get($lockCacheKey); if ($oldExpire >= $time) { continue; } $newExpire = $time + $timeout; $expireAt = $this->redis->getset($lockCacheKey, $newExpire); if ($oldExpire != $expireAt) { continue; } $isGet = $newExpire; break; } return $isGet; } // 释放锁 public function releaseLock($key, $newExpire) { $lockCacheKey = $this->getLockCacheKey($key); if ($newExpire >= time()) { return $this->redis->del($lockCacheKey); } return true; } }
以下是调用演示代码
$redis = new \Redis(); $redis->connect('127.0.0.1', '6379'); $lockTimeOut = 10; $redisLock = new RedisLockService($redis, $lockTimeOut); $lockKey = 'lock:user:wallet:uid:1001'; $lockExpire = $redisLock->getLock($lockKey, 10); if($lockExpire){ $model = $models = Admin::lockForUpdate()->where('id',13)->first(); $model->point = ($model->point - 30); $model->save(); } $redisLock->releaseLock($lockKey,$lockExpire); die('ok');
使用这个锁,会影响处理的吞吐量。
请自行考量。