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
相关推荐
Miqiuha2 小时前
生成唯一id
分布式
㳺三才人子3 小时前
初探 Spring Framework OncePerRequestFilter
spring boot·spring·junit
liuc03174 小时前
AI下调用redis并调用deepseek
数据库·redis·mybatis
遇见火星5 小时前
Redis主从复制深度解析:数据高可用与负载均衡的核心方案
数据库·redis·缓存·负载均衡
哈里谢顿8 小时前
MySQL + Redis 协同 示例
redis·mysql
左灯右行的爱情8 小时前
Kafka专辑- 整体架构
分布式·架构·kafka
哈里谢顿10 小时前
redis实现排行榜功能
redis
山上春10 小时前
Odoo 分布式单体与微服务模式深度对比研究报告
分布式·微服务·架构
左灯右行的爱情10 小时前
Kafka专辑 : 生产者写入路径
分布式·kafka·linq
java1234_小锋11 小时前
Zookeeper集群数据是如何同步的?
分布式·zookeeper·云原生