From 1d350536fc4d5de49cf76973a94e690f3cad1759 Mon Sep 17 00:00:00 2001 From: guide Date: Thu, 1 Sep 2022 15:49:37 +0800 Subject: [PATCH] =?UTF-8?q?[docs=20update]Redisson=20=E7=9C=8B=E9=97=A8?= =?UTF-8?q?=E7=8B=97=E5=8E=9F=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/distributed-system/distributed-lock.md | 92 ++++++++++++++++-- .../distributed-lock-setnx.png | Bin 0 -> 21940 bytes 2 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 docs/distributed-system/images/distributed-lock/distributed-lock-setnx.png diff --git a/docs/distributed-system/distributed-lock.md b/docs/distributed-system/distributed-lock.md index 28723a5f..3fd618dc 100644 --- a/docs/distributed-system/distributed-lock.md +++ b/docs/distributed-system/distributed-lock.md @@ -1,8 +1,6 @@ --- title: 分布式锁 category: 分布式 - - --- 网上有很多分布式锁相关的文章,写了一个相对简洁易懂的版本,针对面试和工作应该够用了。 @@ -19,7 +17,7 @@ category: 分布式 分布式系统下,不同的服务/客户端通常运行在独立的 JVM 进程上。如果多个 JVM 进程共享同一份资源的话,使用本地锁就没办法实现资源的互斥访问了。于是,**分布式锁** 就诞生了。 -举个例子:系统的订单服务一共部署了 3 份,都对外提供服务。用户下订单之前需要检查库存,为了防止超卖,这里需要加锁以实现对检查库存操作的同步访问。由于订单服务位于不同的 JVM 进程中,本地锁在这种情况下就没办法正常工作了。我们需要用到分布式锁,这样的话,即使多个线程不在同一个 JVM 进程中也能获取到同一把锁,进而实现共享资源的互斥访问。 +举个例子:系统的订单服务一共部署了 3 份,都对外提供服务。用户下订单之前需要检查库存,为了防止超卖,这里需要加锁以实现对检查库存操作的同步访问。由于订单服务位于不同的 JVM 进程中,本地锁在这种情况下就没办法正常工作了。我们需要用到分布式锁,这样的话,即使多个线程不在同一个 JVM 进程中也能获取到同一把锁,进而实现共享资源的互斥访问。 下面是我对分布式锁画的一张示意图。 @@ -69,6 +67,8 @@ else end ``` +![Redis 实现简易分布式锁](images/distributed-lock/distributed-lock-setnx.png) + 这是一种最简易的 Redis 分布式锁实现,实现方式比较简单,性能也很高效。不过,这种方式实现分布式锁存在一些问题。就比如应用程序遇到一些问题比如释放锁的逻辑突然挂掉,可能会导致锁无法被释放,进而造成共享资源无法再被其他线程/进程访问。 ### 为什么要给锁设置一个过期时间? @@ -91,20 +91,92 @@ OK 你或许在想: **如果操作共享资源的操作还未完成,锁过期时间能够自己续期就好了!** +### 如何实现锁的优雅续期? + 对于 Java 开发的小伙伴来说,已经有了现成的解决方案:**[Redisson](https://github.com/redisson/redisson)** 。其他语言的解决方案,可以在 Redis 官方文档中找到,地址:https://redis.io/topics/distlock 。 ![Distributed locks with Redis](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/redis-distributed-lock.png) -Redisson 是一个开源的 Java 语言 Redis 客户端,提供了很多开箱即用的功能,不仅仅包括多种分布式锁的实现。 +Redisson 是一个开源的 Java 语言 Redis 客户端,提供了很多开箱即用的功能,不仅仅包括多种分布式锁的实现。并且,Redisson 还支持 Redis 单机、Redis Sentinel 、Redis Cluster 等多种部署架构。 -Redisson 中的分布式锁自带自动续期机制,它提供了一个专门用来监控锁的 **Watch Dog( 看门狗)**,如果操作共享资源的还未完成的话,Watch Dog 会不断地延长锁的过期时间,进而保证锁不会因为超时而被释放。 +Redisson 中的分布式锁自带自动续期机制,使用起来非常简单,原理也比较简单,其提供了一个专门用来监控和续期锁的 **Watch Dog( 看门狗)**,如果操作共享资源的线程还未执行完成的话,Watch Dog 会不断地延长锁的过期时间,进而保证锁不会因为超时而被释放。 + +看门狗名字的由来于 `getLockWatchdogTimeou()` 方法,这个方法返回的是看门狗给锁续期的过期时间,默认为 30 秒([redisson-3.17.6](https://github.com/redisson/redisson/releases/tag/redisson-3.17.6))。 + +```java +//默认 30秒,支持修改 +private long lockWatchdogTimeout = 30 * 1000; + +public Config setLockWatchdogTimeout(long lockWatchdogTimeout) { + this.lockWatchdogTimeout = lockWatchdogTimeout; + return this; +} +public long getLockWatchdogTimeout() { + return lockWatchdogTimeout; +} +``` + +`renewExpiration()` 方法包含了看门狗的主要逻辑: + +```java +private void renewExpiration() { + //...... + Timeout task = commandExecutor.getConnectionManager().newTimeout(new TimerTask() { + @Override + public void run(Timeout timeout) throws Exception { + //...... + // 异步续期,基于 Lua 脚本 + CompletionStage future = renewExpirationAsync(threadId); + future.whenComplete((res, e) -> { + if (e != null) { + // 无法续期 + log.error("Can't update lock " + getRawName() + " expiration", e); + EXPIRATION_RENEWAL_MAP.remove(getEntryName()); + return; + } + + if (res) { + // 递归调用实现续期 + renewExpiration(); + } else { + // 取消续期 + cancelExpirationRenewal(null); + } + }); + } + // 延迟 internalLockLeaseTime/3(默认 10s,也就是 30/3) 再调用 + }, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS); + + ee.setTimeout(task); + } +``` + +默认情况下,每过 10 秒,看门狗就会执行续期操作,将锁的超时时间设置为 30 秒。看门狗续期前也会先判断是否需要执行续期操作,需要才会执行续期,否则取消续期操作。 + +Watch Dog 通过调用 `renewExpirationAsync()` 方法实现锁的异步续期: + +```java +protected CompletionStage renewExpirationAsync(long threadId) { + return evalWriteAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, + // 如果指定的锁存在就续期,将其过期时间设置为 30s(默认) + "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " + + "redis.call('pexpire', KEYS[1], ARGV[1]); " + + "return 1; " + + "end; " + + "return 0;", + Collections.singletonList(getRawName()), + internalLockLeaseTime, getLockName(threadId)); +} +``` + +可以看出, `renewExpirationAsync` 方法其实是调用 Lua 脚本实现的续期,这样做主要是为了保证续期操作的原子性。 我这里以 Redisson 的分布式可重入锁 `RLock` 为例来说明如何使用 Redisson 实现分布式锁: ```java // 1.获取指定的分布式锁对象 RLock lock = redisson.getLock("lock"); -// 2.拿锁,具有 Watch Dog 自动续期机制 +// 2.拿锁且不设置锁超时时间,具备 Watch Dog 自动续期机制 lock.lock(); // 3.执行业务 ... @@ -112,7 +184,12 @@ lock.lock(); lock.unlock(); ``` -可以看出,代码非常简洁直观。 +只有未指定锁超时时间,才会使用到 Watch Dog 自动续期机制。 + +```java +// 手动给锁设置过期时间,不具备 Watch Dog 自动续期机制 +lock.lock(10, TimeUnit.SECONDS); +``` 如果使用 Redis 来实现分布式锁的话,还是比较推荐直接基于 Redisson 来做的。 @@ -135,4 +212,3 @@ Redlock 实现比较复杂,性能比较差,发生时钟变迁的情况下还 实际项目中不建议使用 Redlock 算法,成本和收益不成正比。 如果不是非要实现绝对可靠的分布式锁的话,其实单机版 Redis 就完全够了,实现简单,性能也非常高。如果你必须要实现一个绝对可靠的分布式锁的话,可以基于 Zookeeper 来做,只是性能会差一些。 - diff --git a/docs/distributed-system/images/distributed-lock/distributed-lock-setnx.png b/docs/distributed-system/images/distributed-lock/distributed-lock-setnx.png new file mode 100644 index 0000000000000000000000000000000000000000..aebf75f21cbdff57f31689fd9903769db4c66e1b GIT binary patch literal 21940 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 M07*qoM6N<$f}^dI0ssI2 literal 0 HcmV?d00001