Redis分布式锁初探

Redis分布式锁实现及死锁解决
本文介绍了Redis分布式锁的实现方式,使用SETNX、SET、GETSET等命令。指出仅用SETNX加锁存在缺陷,若持有锁的节点异常,会导致死锁。采用GETSET命令可解决此问题,当上一锁超时时,后续节点有机会获取锁。

这里介绍了一种redis分布式锁的实现方式:

主要使用了redis命令为:SETNX,SET,GETSET,详细了解命令见:http://doc.redisfans.com/index.html

为了直观体现,下面是我的加锁实现代码:

import lombok.extern.slf4j.Slf4j;
import org.simpleframework.xml.core.Complete;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;

/**
 * Created by zhangfan on 2019/6/20 14:50
 */
@Complete
@Slf4j
public class RedisLock {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     *
     * @param key productId(商品id)
     * @param value  当前时间+过期时间
     * @return
     */
    public boolean lock(String key, String value){
        //使用redis的SETNX方法,加锁
        if(redisTemplate.opsForValue().setIfAbsent(key,value)){
            return true;
        }
        String currentValue = redisTemplate.opsForValue().get(key);
        //锁过期了
        if(!StringUtils.isEmpty(currentValue)
                && Long.parseLong(currentValue) < System.currentTimeMillis()){
            String oldValue = redisTemplate.opsForValue().getAndSet(key,value);
            if(!oldValue.isEmpty() && oldValue.equals(currentValue)){
                return true;
            }
        }
        return false;
    }
}

其中setIfAbsent()方法为SETNX方法,getAndSet()方法为GETSET方法。

虽然SETNX命令就可以做到加锁操作,当一个线程执行方法成功时则获取锁,其他线程等待,但是这有个致命的缺陷,就是当前执有锁的节点在执行java代码时,出现了异常,那么他就会抛出异常而不会释放锁,就会导致其他节点都不会拿到锁,造成死锁等待。

那么我下面用了GETSET命令,则是当上一个锁A因为某种原因超时了,那么就会有机会让下面的节点B获取到锁,主要原理是:首先我们获取当前key(A)的value,判断他锁超时了,那么就会用GETSET命令获取key的旧值value->A,判断他们相同则就可以让节点B获取锁。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值