跳到主要内容

分布式锁

  • 分布式锁的特性
    1. 互斥性:任何时刻,对于同一条数据,只有一个应用可以获取到分布式锁
    2. 高可用性:分布式场景下,一小部分服务器宕机不影响正常使用,以集群方式部署实现分布式锁
    3. 防止锁超时:客户端如果没有主动释放锁,服务器会在一段时间后自动释放锁,防止客户端宕机或者网络问题导致死锁
    4. 独占性:加解锁必须由同一台服务器进行,只有锁的持有者才能释放锁

分布式锁的实现

手动实现

锁的获取

  • SETNX:意为 SET if not exists,用法 SETNX key value
    使用时需要添加过期时间,否则如果不进行手动释放,会一直占用锁

    SET Key 1
    EXPIRE key seconds

    获取锁和设置过期时间分成了两部,不是原子性操作,有可能导致获取锁成功,设置过期时间失败

  • SETEX:用法 SETEX key seconds value,将 key 的值设为 value ,并且设置过期时间为 seconds 秒,如果 key 已经存在,则将进行覆盖,类似于以下命令,但是是原子性操作

    SET key value
    EXPIRE key seconds # 设置生存时间
  • PSETEX:用法 PSETEX key milliseconds value,和 SETEX 类似,但是指定过期时间单位为毫秒

锁的释放

  • 直接删除 key 即可,但是需要确保当前释放锁的线程是锁的持有者,这个操作需要两个步骤,因此又不是原子性操作了,可以使用 lua 脚本进行拼装,保证操作的原子性
    # KEYS[1] 代表当前 key 名称,ARGV[1] 代表线程ID(或其他能识别所属线程的标识)
    if redis.call("get",KEYS[1]) == ARGV[1]
    then
    return redis.call("del",KEYS[1])
    else
    return 0
    end