Redis实现分布式锁

本文介绍了如何利用Redis来实现分布式锁,包括基础方法、流程图和具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 基础方法

/**
 * 如果为空就插入值,返回true,如果不为空则不做操作,返回false
 * @param key
 * @param value
 * @return
 */
public static Boolean setIfAbsent(String key, String value){
    return redisTemplate.opsForValue().setIfAbsent(key, value);
}
/**
 * 插入新值并返回旧值
 * @param key
 * @param value
 * @return
 */
public static String getAndSet(String key, String value){
    return redisTemplate.opsForValue().getAndSet(key, value);
}

2 流程图

这里写图片描述

3 代码

/**
 * 获取分布式锁,获取不成功会一直尝试获取
 * @param redisKey
 * @return
 */
public static boolean getDistributedLock(StrRedisKey redisKey){
    try {
        String currentMill= DateUtil.current(false) + "";
        while (true){
            Boolean getLock =RedisClientUtil.setIfAbsent(redisKey.getDataBaseKey(), currentMill);
            if(getLock){
                logger.debug(Thread.currentThread().getName() + "-成功获取分布式锁【"+ redisKey.getDataBaseKey() +"】");
                return true;
            }else {
                logger.debug(Thread.currentThread().getName() + "-获取分布式锁【"+ redisKey.getDataBaseKey() +"】失败,将尝试重新获取锁");
                while (true){
                    String currentLockValue = RedisClientUtil.get(redisKey);
                    long currentLockTime,oldLockTime;
                    if(StrUtil.isNotBlank(currentLockValue)){
                        currentLockTime = Long.parseLong(currentLockValue);
                        if(DateUtil.current(false) - currentLockTime > ConfigUtil.getDistributeLockTimeOutValue()){
                            //锁过期
                            logger.debug(Thread.currentThread().getName() + "-当前的分布式锁【"+ redisKey.getDataBaseKey() +"】已经超时,将尝试强制获取锁");
                            String oldLockValue = RedisClientUtil.getAndSet(redisKey.getDataBaseKey(), DateUtil.current(false) + "");
                            if(StrUtil.isNotBlank(oldLockValue)){
                                oldLockTime = Long.parseLong(oldLockValue);
                                if(currentLockTime == oldLockTime){
                                    //获得锁
                                    logger.debug(Thread.currentThread().getName() + "-成功获取分布式锁【"+ redisKey.getDataBaseKey() +"】");
                                    return true;
                                }else {
                                    //在这之前已经有其他客户端获取锁,等待重试
                                    logger.debug(Thread.currentThread().getName() + "-已经有其他客户端抢先获取到分布式锁【"+ redisKey.getDataBaseKey() +"】,将稍后重试获取锁");
                                    try {
                                        Thread.sleep(50);
                                    } catch (InterruptedException e) {
                                        logger.warn(e.getMessage(),e);
                                    }
                                }
                            }else {
                                //锁被释放,可以获得锁
                                logger.debug(Thread.currentThread().getName() + "-当前分布式锁【"+ redisKey.getDataBaseKey() +"】已经被释放,将尝试重新获取锁");
                                break;
                            }
                        }else {
                            //锁正在有效期被其他客户端使用,等待重试
                            logger.debug(Thread.currentThread().getName() + "-分布式锁【"+ redisKey.getDataBaseKey() +"】正在被其他客户端使用,将稍后重试获取锁");
                            try {
                                Thread.sleep(50);
                            } catch (InterruptedException e) {
                                logger.warn(e.getMessage(),e);
                            }
                        }
                    }else {
                        //锁被释放,可以获得锁
                        logger.debug(Thread.currentThread().getName() + "-当前分布式锁【"+ redisKey.getDataBaseKey() +"】已经被释放,将尝试重新获取锁");
                        break;
                    }
                }
            }
        }
    }catch (Exception ex){
        logger.error(ex.getMessage(),ex);
        return true;
    }
}

/**
 * 尝试获取分布式锁,获取失败则直接返回
 * @param redisKey
 * @return
 */
public static boolean tryGetDistributedLock(StrRedisKey redisKey){
    String currentMill= DateUtil.current(false) + "";
    Boolean getLock =RedisClientUtil.setIfAbsent(redisKey.getDataBaseKey(), currentMill);
    if(getLock){
        logger.debug(Thread.currentThread().getName() + "-成功获取分布式锁【"+ redisKey.getDataBaseKey() +"】");
        return true;
    }
    logger.debug(Thread.currentThread().getName() + "-尝试获取分布式锁【"+ redisKey.getDataBaseKey() +"】失败");
    return false;
}  

/**
 * 释放分布式锁
 * 可能会出现释放不成功的情况,不需处理,只需等待自动超时即可
 * @param redisKey
 * @return
 */
public static boolean releaseDistributedLock(StrRedisKey redisKey){
    RedisClientUtil.delete(redisKey);
    logger.debug(Thread.currentThread().getName() + "-成功释放分布式锁【"+ redisKey.getDataBaseKey() +"】");
    return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值