【redis分布式锁原理】REDIS加锁防止重复操作的原理与例子

更新时间:2020-03-16    来源:redis    手机版     字体:

【www.bbyears.com--redis】

使用Redis加锁的方式可以防止重复操作,包括表单提交,ajax等http请求,它的原理就是redis的incr命令给键自增,如果返回值不是1,就表示是重复请求,具体看代码:

 代码如下

/**
 * 锁定请求
 * @param int $expire 锁定时间
 * @param string $mark 自定义标记
 * @return bool
 */
protected function lock($expire=1,$mark=""){
    $url=strtolower(MODULE_NAME."/".ACTION_NAME);//操作地址
    $prefix="lock_";$sid=$_COOKIE[C("SESSION_OPTIONS.name")];
    $key=$prefix.md5($sid.$url.$mark);//令牌键值
    /**
     * @var Redis $redis
     */
    $redis = D("Redis");
    if($redis->incr($key)==1){
        return $redis->expire($key,$expire);
    }
    return false;
}

这里也要讲讲Redis的incr命令的用法:

INCR key命令用法

将 key 中储存的数字值增一。

如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。

如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。

本操作的值限制在 64 位(bit)有符号数字表示之内。

 代码如下

redis> SET page_view 20
OK
 
redis> INCR page_view
(integer) 21
 
redis> GET page_view    # 数字值在 Redis 中以字符串的形式保存
"21"

返回值是incr之后的值。

如果incr一个不存在的键,它会自动创建这个键并返回值1.

redis incr命令用法

expire 命令示例:


expire key 22

设置键名为key(必须存在)的过期时间为22s.

再回到开始处定义的lock方法,键值为lock+当前操作地址+cookie值+自定义字符串,进行incr操作并使用expire命令设置过期时间默认1s,如是是第一次请求会返回1(expire设置缓存成功),表示设置缓存时间成功,否则返回false表示重复请求或操作。

使用的时候:

 

 代码如下 if(!$this->lock(1)){
  //重复操作了
}

这样就可以判断是重复操作了。

 代码如下


$this->unlock()

这样就解锁了,可以允许第二次一样的提交。

看看解锁方法:

 代码如下

 

/**
 * 解锁请求
 * @param string $mark 自定义标记
 * @return bool
 */
protected function unlock($mark=""){
    $url=strtolower(MODULE_NAME."/".ACTION_NAME);//操作地址
    $prefix="lock_";$sid=$sid=$_COOKIE[C("SESSION_OPTIONS.name")];
    $key=$prefix.md5($sid.$url.$mark);//令牌键值
    /**
     * @var Redis $redis
     */
    $redis = D("Redis");
    return $redis->del($key);
}

这里使用了Redis的del命令。

本文来源:http://www.bbyears.com/shujuku/87441.html