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;
        }
    }
posted @ 2020-04-30 14:31  蜗牛使劲冲  阅读(10)  评论(0)    收藏  举报  来源