Redis实现分布式锁

本文介绍了如何利用Redis的set key value ex expireTime nx命令实现分布式锁,解决了因setnx命令无法设置过期时间导致的死锁问题。通过在设置锁时使用线程ID标识,并用守护线程进行续时,确保了锁的安全释放。详细阐述了加锁、续时、解锁的具体步骤,并提及了Zookeeper作为另一种分布式锁实现方式。
摘要由CSDN通过智能技术生成

Redis实现分布式锁

1 问题导入

使用setnx来实现分布式锁?

2 问题分析

问题1:setnx命令在参数中不能设置过期时间,要执行expire才能进行过期时间设置,不是原子性的操作,可能会在执行setnx后服务器宕机,没有设置expire,从而造成死锁现象

解决:在redis中可以使用set key value ex expireTime nx 命令来进行替换,在代码中可以使用redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.SECONDS)来实现

问题2:当A线程获取锁正在执行时,锁过期了,这时,线程B获取到了锁进入执行,当A线程执行完操作删除锁,实际是删除的B线程持有的锁(出现误删的情况)

解决:可以在设置锁的时候以线程id进行标识,删除时先进行判断,然后再进行删除

问题3:先进行key的判断,再删除key的操作不是原子性的

解决:设置守护线程,在key过期之前进行续时,线程业务执行完后才能进行删除,即使当前线程所在服务器宕机该key也会自动过期释放,不会出现死锁

3 实现原理

  • 1.使用set key value ex expireTime nx命令,此命令是原子性操作,在key不存在的情况下,进行set操作,同时给该key设置一个过期时间
  • 2.应用中可以使用setIfAbsent(key, value, expireTime, TimeUnit.SECONDS)来实现
  • 3.添加一个守护线程来进行key的监控以延长过期时间(续命),直到业务执行完毕

4 具体实现

4.1 加锁

/**
 * 分布式锁(加锁)
 * (setIfAbsent+后台守护线程为其续时)
 * @param key 键
 * @param value 值
 * @param expire 过期时间
 * @return true 成功,false 失败
 */
public boolean setIfAbsent(String key,Object value,long expire){
   
    Boolean flag =false;
    try{
   
        if(expire>0){
   
            flag = redisTemplate.opsForValue().setIfAbsent(key, value, expire, TimeUnit.SECONDS);
        }
    }catch (Exception e){
   
        e.printStackTrace();
    }
    return flag;
}

4.2 续时

/**
 * 分布式锁(续命)
 * 通过守护线程进行key的续时
 * @param key
 * @param expire
 */
public void setExpire(String key ,long expire){
   
    log.info("===>进入setExpire,进行续时操作&
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值