redis 分布式锁

WATCH乐观锁

只会在数据被其他客户端抢先修改的情况下通知执行了这个命令的客户端,而不会阻止其他客户端对数据进行修改

一般用 watch、multi、exec结构包裹

 

SETNX悲观锁

这个命令只有在键不存在的情况下为键设置值,将一个随机生成的值设置为键的值,并使用这个值防止锁被其他进程取得。

程序尝试获取锁失败后会不断重试,直到成功或者超过给定时限

 

细粒度锁

在商品交易时前两种锁锁住的是整个市场,而我们关心的是某件商品,通过只锁住商品二不是整个市场,可以减少锁竞争,提升程序性能

 

为了给锁加上超时限制特性,程序将在取得锁之后,调用EXPIRE命令来为锁设置过期时间,使得Redis可以自动删除超时的锁。为了确保锁在客户端已经崩溃(在执行SETNX和EXPIRE之间崩溃最极端)的情况下仍然能够自动释放,客户端在尝试获取锁失败后,检查锁的超时时间,并为未设置超时时间的锁设置超时时间。Redis2.6.12版本后 直接 使用SET参数设置 过期时间  set key value NX EX ‘时间’ 

 

锁不正确运行的原因

  1. 持有锁的进程因为操作时间长而导致锁被自动释放,但进程不知晓,甚至还释放掉其他进程持有的锁
  2. 一个持有锁并打算执行长时间操作的进程已经崩溃,但其他想获取锁的进程无法检测,白白浪费时间等待锁被释放
  3. 在一个进程持有锁过期后,其他多个进程同时获取锁,并且都获得了锁

 

ThinkPHP6 测试代码:

<?php 
/**
 * +----------------------------------------------------------------------
 * | Redis 互斥锁
 * +----------------------------------------------------------------------
 */
namespace app\common;

use think\facade\Cache;

class RedisLock {

  private $_redis;
  
  public function __construct()
  {
    //获取redis handler资源句柄
    $this->_redis = Cache::handler();

  }
  /**
   * 获取锁
   * @param  String  $key    锁标识
   * @param  Int     $expire 锁过期时间
   * @param  Int     $random   随机值
   * @return Boolean
   */
  public function acquire_lock($key, $random, $expire)
  {
      //设置锁的超时时间,避免释放锁失败,del()操作失败,产生死锁。
      $ret = $this->_redis->set($key, $random, ['nx', 'ex' => $expire]);
      return $ret;
  }
   
  /**
   * 释放锁
   * @param  String  $key 锁标识
   * @param  Int     $random   随机值
   * @return Boolean
   */
  public function release_lock($key, $random)
  {
      //防止操作时间过长,超过了锁的有效时间,导致其他请求拿到了锁,误删其他请求创建的锁
      if ($this->_redis->get($key) == $random) {
        return $this->_redis->del($key);
      }else {
        return 2;
      }
  }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值