Redis实现分布式锁(9)

1.Redis分布式锁实现思路

Redis实现分布式锁基于SetNx命令,因为在Redis中key是保证是唯一的。所以当多个线程同时的创建setNx时,只要谁能够创建成功谁就能够获取到锁。

Set 命令 每次set时,可以修改原来旧值;
SetNx命令 每次SetNx检查该key是否已经存在,如果已经存在的话不会执行任何操作。返回为0 如果已经不存在的话直接新增该key。
返回值: 1-新增key成功 0-失败

获取锁的时候:当多个线程同时创建SetNx k,只要谁能够创建成功谁就能够获取到锁。
释放锁:可以对该key设置一个有效期可以避免死锁的现象。

2.分布式锁的应用场景

  1. 分布式任务调度平台保证任务的幂等性。
  2. 分布式全局id的生成

3.Redis分布式锁核心代码

封装的JedisUtil类可查看前面代码或者 完整的github项目 【springboot-redis(redis-lock)】

3.1 封装获取RedisLockUtil 工具类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.UUID;

/**
 * @author 若成风
 * @description
 * @date 2022/9/7 23:45
 * @copyright (c) 2022, all rights reserved
 **/
@Component
public class RedisLockUtil {
    @Autowired
    private JedisUtil jedisUtil;
    private static final int setnxSuccss = 1;

    /**
     *  获取锁
     *  timeOut 时间为毫秒
     *  示例: getLock("lockKey" , 3000, 5000)
     *  申请尝试加锁,最大等待时间3秒,上锁5秒后自动解锁
     * @param lockKey           定义锁的key
     * @param lockWaitTimeOut   申请锁的最大等待时间,超过则申请锁失败
     * @param lockTimeOut       锁的超时时间
     * @return
     */
    public String getLock(String lockKey, int lockWaitTimeOut, int lockTimeOut) {
        // 获取Redis连接
        // 定义没有获取锁的超时时间
        Long endTimeOut = System.currentTimeMillis() + lockWaitTimeOut;
        while (System.currentTimeMillis() < endTimeOut) {
            String lockValue = UUID.randomUUID().toString();
            // 如果在多线程情况下谁能够setnx 成功返回0 谁就获取到锁
            Long nx = jedisUtil.setnx(lockKey, lockValue, lockTimeOut / 1000);
            if (setnxSuccss == nx) {
                return lockValue;
            }
            // 否则情况下 在超时时间内继续循环
        }
        return null;
    }

    /**
     * 释放锁 其实就是将该key删除
     * @return
     */
    public Boolean unLock(String lockKey, String lockValue) {
        // 确定是对应的锁 ,才删除
        if (StringUtils.isNotBlank(lockValue) && lockValue.equals(jedisUtil.get(lockKey))) {
            return jedisUtil.del(lockKey) > 0 ? true : false;
        }
        return false;
    }
}

3.2测试使用分布式锁

import com.redmaple.common.util.RedisLockUtil;
import com.redmaple.service.OrderService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author 若成风
 * @description
 * @date 2022/9/8 23:06
 * @copyright (c) 2022, all rights reserved
 **/
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private RedisLockUtil redisLockUtil;
    private String lockKey = "redmaple_lock";

    @Async("myThreadPool")
    @Override
    public void testService() {
        // 1.获取锁
        String lockValue = redisLockUtil.getLock(lockKey, 500, 60000);
        try {
            if (StringUtils.isEmpty(lockValue)) {
                System.out.println(Thread.currentThread().getName() + ",获取锁失败!");
                return;
            }
            // 2.获取锁成功执行业务逻辑
            System.out.println(Thread.currentThread().getName() + ",获取成功,lockValue:" + lockValue);
            Thread.sleep(2000);
        } catch (Exception e) {
            log.error("分布式锁", e);
        } finally {
            // 防止代码执行完成后,或发生异常后,主动释放锁
            // 3.释放lock锁
            redisLockUtil.unLock(lockKey, lockValue);
        }
    }
}
@RestController
public class RedisLockController {

    @Autowired
    private OrderService orderService;

    @GetMapping("/testRedisLock")
    public String testRedisLock() {
        System.out.println("=====  start  ======");
        for (int i = 0; i < 10; i++) {
            orderService.testService();
        }
        return "===  success  ===";
    }

}

如果该文章能够帮助到你,希望麻烦一键三连下,谢谢

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值