redis锁的实际应用
以前对redis上锁概念一直不太清楚,现在来整理下
其实就是当你的一次操作要保证数据的原子性和一致性,你需要先加个锁(这个加锁的动作其实也包含了验证是否上锁),然后进行操作,完了即使没有成功也要解锁,这个redis的操作为什么要用lua语句因为要保证原子操作
解锁的原则:在一个用户下
如下示例:
$lockKey = __FUNCTION__ . $studentId;
$lockValue = CacheUtil::redisLock($lockKey);
if($lockValue === false) {
throw GoodsException::error(20200006);
}
try {
/**
一系列对于学生信息各种表的操作
*/
CacheUtil::redisUnlock($lockKey, $lockValue);
return $result;
}catch (Exception $e) {
CacheUtil::redisUnlock($lockKey, $lockValue);
Log::error($msg . '| error:'. $e->getMessage());
if($e instanceof BaseException) {
throw $e;
}
throw GoodsException::error(20300001);
}
以上set参数详解见我另一篇传送门
public static function redisLock(string $key, $time = 5)
{
try {
$value = rand(1, 9999);
if (Redis::set($key . '_lock', $value, 'ex', $time, 'nx')) {
Log::info("Redis lock success: key: {$key} value: {$value}");
return $value;
} else {
Log::error("Redis lock failed: key: {$key} value: {$value}");
return false;
}
}catch (\RedisException $e) {
Log::error("Redis lock failed: key: {$key} Exception:" . json_encode($e));
return false;
}
}
public static function redisUnlock(string $key, int $value)
{
try {
$script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
if (Redis::eval($script, 1, $key . '_lock', $value)) {
Log::info("Redis unlock success: key: {$key} value: {$value}");
return true;
} else {
Log::error("Redis unlock failed: key: {$key} value: {$value}");
return false;
}
}catch (\RedisException $e) {
Log::error("Redis unlock failed: key: {$key} value: {$value} Exception:" . json_encode($e));
return false;
}
}

浙公网安备 33010602011771号