redis实现分布式锁

redis实现分布式锁

java 复制代码
@Component
public class RedisDistributedLock {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String LOCK_PREFIX = "lock:";
    private static final long DEFAULT_EXPIRE = 30_000; // 默认30秒

    // 加锁(带UUID防误删)
    public String tryLock(String lockKey, long expire) {
        String requestId = UUID.randomUUID().toString();
        boolean result = redisTemplate.opsForValue().setIfAbsent(LOCK_PREFIX + lockKey, requestId, expire, TimeUnit.MILLISECONDS);
        return result ? requestId : null;
    }

    // 解锁(验证锁持有者身份后删除)
    public boolean unlock(String lockKey, String requestId) {
        String key = LOCK_PREFIX + lockKey;
        String currentRequestId = redisTemplate.opsForValue().get(key);
        if (requestId.equals(currentRequestId)) {
            return redisTemplate.delete(key);
        }
        return false;
    }
}

lua脚本实现方式

java 复制代码
public class RedisDistributedLock {
    
    private RedisTemplate<String, Object> redisTemplate;
    private String lockKey;
    private String lockValue;
    private int expireTime;
    
    // 获取锁的Lua脚本
    private static final String ACQUIRE_LOCK_SCRIPT = 
        "if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then " +
        "redis.call('expire', KEYS[1], tonumber(ARGV[2])) " +
        "return 1 " +
        "else " +
        "return 0 " +
        "end";
        
    // 释放锁的Lua脚本
    private static final String RELEASE_LOCK_SCRIPT = 
        "if redis.call('get', KEYS[1]) == ARGV[1] then " +
        "return redis.call('del', KEYS[1]) " +
        "else " +
        "return 0 " +
        "end";
    
    public RedisDistributedLock(RedisTemplate<String, Object> redisTemplate, 
                               String lockKey, int expireTime) {
        this.redisTemplate = redisTemplate;
        this.lockKey = lockKey;
        this.expireTime = expireTime;
        this.lockValue = UUID.randomUUID().toString();
    }
    
    /**
     * 尝试获取分布式锁
     * @return 是否获取成功
     */
    public boolean tryLock() {
        RedisScript<Long> script = new DefaultRedisScript<>(ACQUIRE_LOCK_SCRIPT, Long.class);
        Long result = redisTemplate.execute(script, 
                                          Collections.singletonList(lockKey), 
                                          lockValue, 
                                          String.valueOf(expireTime));
        return result != null && result == 1;
    }
    
    /**
     * 释放分布式锁
     * @return 是否释放成功
     */
    public boolean releaseLock() {
        RedisScript<Long> script = new DefaultRedisScript<>(RELEASE_LOCK_SCRIPT, Long.class);
        Long result = redisTemplate.execute(script, 
                                          Collections.singletonList(lockKey), 
                                          lockValue);
        return result != null && result == 1;
    }
    
    /**
     * 带超时的获取锁方法
     * @param timeout 超时时间(毫秒)
     * @return 是否获取成功
     */
    public boolean tryLock(long timeout) {
        long startTime = System.currentTimeMillis();
        do {
            if (tryLock()) {
                return true;
            }
            try {
                Thread.sleep(100); // 短暂休眠避免过度竞争
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return false;
            }
        } while (System.currentTimeMillis() - startTime < timeout);
        
        return false;
    }
}

代码说明:

  1. 使用RedisTemplate的setIfAbsent方法实现原子加锁操作
  2. 通过UUID生成唯一请求ID,防止误删其他客户端的锁
  3. 解锁时通过Lua脚本验证锁持有者身份,确保原子性
  4. 支持自定义过期时间,防止死锁
  5. 依赖Spring框架,需配置RedisTemplate Bean
相关推荐
qq_12498707532 小时前
基于Hadoop的信贷风险评估的数据可视化分析与预测系统的设计与实现(源码+论文+部署+安装)
大数据·人工智能·hadoop·分布式·信息可视化·毕业设计·计算机毕业设计
曾经的三心草2 小时前
redis-9-哨兵
数据库·redis·bootstrap
张小凡vip2 小时前
Kubernetes--k8s中部署redis数据库服务
redis·kubernetes
惊讶的猫3 小时前
Redis持久化介绍
数据库·redis·缓存
Coder_Boy_4 小时前
基于Spring AI的分布式在线考试系统-事件处理架构实现方案
人工智能·spring boot·分布式·spring
啦啦啦_99994 小时前
Redis-5-doFormatAsync()方法
数据库·redis·c#
生产队队长5 小时前
Redis:Windows环境安装Redis,并将 Redis 进程注册为服务
数据库·redis·缓存
袁煦丞 cpolar内网穿透实验室5 小时前
远程调试内网 Kafka 不再求运维!cpolar 内网穿透实验室第 791 个成功挑战
运维·分布式·kafka·远程工作·内网穿透·cpolar
人间打气筒(Ada)6 小时前
GlusterFS实现KVM高可用及热迁移
分布式·虚拟化·kvm·高可用·glusterfs·热迁移
xu_yule6 小时前
Redis存储(15)Redis的应用_分布式锁_Lua脚本/Redlock算法
数据库·redis·分布式