springboot 使用RedisTemplate构建分布式锁

本文介绍了一种使用Redis和Lua脚本实现分布式锁的方法,通过示例代码详细展示了如何尝试获取和释放分布式锁,适用于高并发场景下资源的独占访问。

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

话不多说直接上源码:

import java.util.Collections;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;


/**
 * 使用redis构建分布式锁(使用lun语言)
 * @author fangyuan
 *
 */
public class RedisLock {
    
    private static final Long RELEASE_SUCCESS = 1L;

    /**
     * 尝试获取分布式锁
     * @param redisTemplate Redis客户端
     * @param lockKey 锁 redis key
     * @param requestId 请求标识 redis value
     * @param expireTime lock超期时间
     * @return 是否获取成功
     */
    public static boolean tryGetDistributedLock(RedisTemplate redisTemplate , String lockKey, String requestId, int expireTime) {

        String scriptText = "if redis.call('setNx',KEYS[1],ARGV[1]) == 1 then if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('expire',KEYS[1],ARGV[2]) else return 0 end else return 0 end";

        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();

        redisScript.setResultType(Long.class);
        redisScript.setScriptText(scriptText);

        Long result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey),requestId,String.valueOf(expireTime));

        if(RELEASE_SUCCESS.equals(result)){
            return true;
        }
        return false;
    }
    

    /**
     * 释放分布式锁
     * @param redisTemplate Redis客户端
     * @param lockKey 锁
     * @param requestId 请求标识
     * @return 是否释放成功
     */
    public static boolean releaseDistributedLock(RedisTemplate redisTemplate, String lockKey, String requestId) {

        String scriptText = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();

        redisScript.setResultType(Long.class);
        redisScript.setScriptText(scriptText);


        Long result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), requestId);

        if (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }

其中需要设置RedisTemplate 对于Key,Value的序列化器为StringRedisSerializer

RedisTemplate<String, Object> template = new RedisTemplate<>();

StringRedisSerializer srs = new StringRedisSerializer();

template.setKeySerializer(srs);
template.setValueSerializer(srs);

使用:

        String lockKey = CacheConstant.LOCK_KEY;

        //随机生成id
        String requestId = UUID.randomUUID().toString();

        //加入分布式锁保证只有一个请求操作
        if(RedisLock.tryGetDistributedLock(dtcRedisTemplate,lockKey,requestId,expireTime)){
            try{
                //业务代码
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                RedisLock.releaseDistributedLock(dtcRedisTemplate,lockKey,requestId);
            }

        }else{
            throw new RuntimeException("该分布式锁已被使用。。。。");
        }
       

后续会使用zookeeper构建分布式锁,并总结两者不同,以及两种方式的不同使用场景

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值