redis实现分布式项目锁机制

一、  背景:我的项目是分布式的,当订单失败要退款时,由于分布式高并发的环境,一笔订单在设备租借失败确认多次上报后会发生多次退款请求导致账户异常。

二、解决方案:使用redis缓存来实现分布式项目加锁控制。

三、了解下redis几个原子命令

setnx 先判断键是否存在,key存在设置失败,返回0;否则成功返回1

getset 获取旧的值,设置新的值

expire 设置键的有效期

del 删除键

四、实现方案流程图:

如上图所示:之前部分步骤一样,只是当获取锁失败后,使用get获取当前锁的value=lockvalueA,如果当前的时间>lockvalueA,说明setnx时timeout现在已经超时了,此时有权利获取锁;此时为true再使用getset方法重新设置一个当前的value值并返回旧的value=lockvalueB,这时做判断,如果lockvalueB==null(锁已经没有了,可以获取到锁)或者lockvalueA==lockvalueB(最新获取的B与之前得到的A相等,在这个过程中锁没有变化)满足则获取锁成功,执行expire业务逻辑,否则结束。

五、代码演示:

public class GlobalConfig {

    // redis 分布式锁
    public static final String REDIS_LOCK_KEY="REDIS_LOCK_KEY";
    // redis 分布式锁过期时间
    public static final String REDIS_LOCK_KEY_EXPIRE_TIME="60";

}
    private boolean lock() {
            Integer expireTime = Integer.valueOf(GlobalConfig.REDIS_LOCK_KEY_EXPIRE_TIME);
            Long setnx = redisService.setnx(GlobalConfig.REDIS_LOCK_KEY, System.currentTimeMillis() +  expireTime * 1000 + ""); //不存在就设置key的值为过期时间1分钟加上当前时间
            if (setnx != null && setnx > 0) {
                redisService.expire(GlobalConfig.REDIS_LOCK_KEY, expireTime);// 设置过期时间1分钟
                return true;
            } else {
                String lockvalueAString = redisService.getString(GlobalConfig.REDIS_LOCK_KEY);
                if(!StringUtil.isNullOrEmpty(lockvalueAString)){
                    Long lockvalueA = Long.valueOf(lockvalueAString);
                    if(lockvalueA!=null && System.currentTimeMillis()>lockvalueA){
                        String lockvalueB = redisService.getSet(GlobalConfig.REDIS_LOCK_KEY, System.currentTimeMillis() + 60 * 1000 + "");
                        if(lockvalueB==null || lockvalueAString.equals(lockvalueB)){
                            redisService.expire(GlobalConfig.REDIS_LOCK_KEY, expireTime);// 设置过期时间1分钟
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        private  void unlock(){
            redisService.del(GlobalConfig.REDIS_LOCK_KEY);
        }


//调用

      if(lock()){

             业务代码逻辑
             
              unlock();
        }
                            

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值