欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 名人名企 > 原生redis实现分布式锁

原生redis实现分布式锁

2025/2/7 8:03:11 来源:https://blog.csdn.net/format_push/article/details/145471402  浏览:    关键词:原生redis实现分布式锁

原生 Redis(Jedis、Lettuce) 实现分布式锁,可以参考 Redisson 的原理,但需要自己处理锁的自动续期、故障恢复等细节。核心思路是使用 Redis 的 SET NX EXSET PX NX 命令来实现互斥锁,并利用 Lua 脚本 保障原子性。

实现思路

  • 获取锁
    • SET key value NX PX expiration,确保锁只能被一个线程获取,并设置过期时间。
  • 自动续期
    • 通过 后台线程 定时续期,防止业务执行时间过长导致锁超时释放。
  • 释放锁
    • 通过 Lua 脚本 保证原子性,只有 当前线程 持有锁时才能释放。

完整代码

1. 依赖引入

使用 Jedis 作为 Redis 客户端:

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.1</version>
</dependency>

2. 分布式锁实现

获取锁
import redis.clients.jedis.Jedis;
import java.util.UUID;public class RedisLock {private static final String LOCK_SUCCESS = "OK";private static final String LOCK_KEY = "my_lock";private static final int EXPIRE_TIME = 10_000; // 10秒过期private final Jedis jedis;private final String lockValue; // 唯一标识锁的持有者public RedisLock(Jedis jedis) {this.jedis = jedis;this.lockValue = UUID.randomUUID().toString(); // 防止误删}public boolean tryLock() {String result = jedis.set(LOCK_KEY, lockValue, "NX", "PX", EXPIRE_TIME);return LOCK_SUCCESS.equals(result); // 返回 true 代表加锁成功}
}
自动续期

如果业务执行时间超过 10s,锁会自动释放,所以需要定时续期

import java.util.concurrent.*;public class LockRenewal {private static final int RENEWAL_INTERVAL = 5000; // 每5秒续期private final Jedis jedis;private final String lockValue;private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);public LockRenewal(Jedis jedis, String lockValue) {this.jedis = jedis;this.lockValue = lockValue;}public void startRenewal() {scheduler.scheduleAtFixedRate(() -> {if (lockValue.equals(jedis.get("my_lock"))) {jedis.pexpire("my_lock", 10_000);}}, 0, RENEWAL_INTERVAL, TimeUnit.MILLISECONDS);}public void stopRenewal() {scheduler.shutdown();}
}
释放锁

使用 Lua 脚本,确保只有 持有锁的线程 才能删除:

public void unlock() {String luaScript ="if redis.call('get', KEYS[1]) == ARGV[1] then " +"   return redis.call('del', KEYS[1]) " +"else " +"   return 0 " +"end";jedis.eval(luaScript, 1, "my_lock", lockValue);
}

3. 使用示例

Jedis jedis = new Jedis("localhost", 6379);
RedisLock redisLock = new RedisLock(jedis);
LockRenewal renewal = new LockRenewal(jedis, redisLock.lockValue);if (redisLock.tryLock()) {renewal.startRenewal(); // 开启自动续期try {// 执行业务逻辑System.out.println("获取到锁,执行业务...");Thread.sleep(15000); // 模拟业务执行时间超过锁的原始超时时间} catch (InterruptedException e) {e.printStackTrace();} finally {redisLock.unlock();renewal.stopRenewal(); // 停止续期}
} else {System.out.println("获取锁失败");
}

总结

  1. 互斥性SET NX PX 确保只有一个线程能获取锁。
  2. 自动续期:定期 PEXPIRE 延长锁的存活时间。
  3. 安全释放:Lua 脚本保证只有锁的持有者才能删除。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com