php实现redis锁

直接上代码

use Illuminate\Support\Facades\Redis;

class CacheController extends Controller
{
    const REDIS_LOCK = 'redis_Lock';    //设置这个为了防止和网站其他的redis键值冲突

    const EXPIRE_TIME = 10;     //锁生存时间

   /**
     * 加锁
     * setnx 如果key不存在,则返回设置成功1
     * 如果key存在,则返回设置失败0,而且值不会被替换。
     * 要设置过期时间,避免死锁。
     * ttl 如果key不存在返回(也可以理解为过期) -2
     * 如果没有设置生存时间返回-1
     * 否在,返回key剩余生存时间
     */

    public static function setLock( $key, $expire = self::EXPIRE_TIME ){
        $key = self::REDIS_LOCK . $key;
        $isLock = Redis::setnx( $key, 1 );
    
        if( !$isLock ){
            //本来这里没必要处理了,但是为了防止特殊情况,锁设置成功,但是Redis::expire设置缓存时间失败,这样会导致死锁
            if( Redis::ttl( $key ) == -1  ){
                Redis::del( $key );
                $isLock = Redis::setnx( $key, 1 );
                if( $isLock ){
                    Redis::expire( $key , $expire );
                }
            }
        }else{
            //获取锁成功,设置生存时间
            Redis::expire( $key , $expire );
        }
        return $isLock ? true : false;

    }

    /**
     * 删除锁
     */

    public static function delLock( $key ){
        return Redis::del( self::REDIS_LOCK.  $key );

    }

}


    使用场景:高并发时,在没有缓存的情况下,只允许第一个请求读取数据库。

        if( CacheController::setLock( $redisKey, 20 ) ){//设置锁
                $list=读取数据库信息
                    
                 //设置缓存
                CacheController::setex( $redisKey, $cacheTime, json_encode( $list ) );
                    
                //删除锁
                CacheController::delLock( $redisKey );
                    
                return=返回结果
        }else{
                //等待
                return=告诉前端其他用户要等待(前端可以隔一段时间请求一次(1-2秒,自定义))

        }


你可能感兴趣的:(php实现redis锁)