diff --git a/.gitignore b/.gitignore index 49a42094..aa4674bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /node_modules /package-lock.json +\*.drawio .DS_Store # VS Code Config file .vscode/ diff --git a/docs/distributed-system/distributed-lock.md b/docs/distributed-system/distributed-lock.md index 041a5173..28723a5f 100644 --- a/docs/distributed-system/distributed-lock.md +++ b/docs/distributed-system/distributed-lock.md @@ -1,13 +1,31 @@ --- title: 分布式锁 category: 分布式 + + --- 网上有很多分布式锁相关的文章,写了一个相对简洁易懂的版本,针对面试和工作应该够用了。 ## 什么是分布式锁? -对于单机多线程,在 Java 中,我们通常使用 `ReetrantLock` 这类 JDK 自带的 **本地锁** 来控制本地多个线程对本地共享资源的访问。对于分布式系统,我们通常使用 **分布式锁** 来控制多个服务对共享资源的访问。 +对于单机多线程来说,在 Java 中,我们通常使用 `ReetrantLock` 类、`synchronized` 关键字这类 JDK 自带的 **本地锁** 来控制一个 JVM 进程内的多个线程对本地共享资源的访问。 + +下面是我对本地锁画的一张示意图。 + +![本地锁](./images/distributed-lock/jvm-local-lock.png) + +从图中可以看出,这些线程访问共享资源是互斥的,同一时刻只有一个线程可以获取到本地锁访问共享资源。 + +分布式系统下,不同的服务/客户端通常运行在独立的 JVM 进程上。如果多个 JVM 进程共享同一份资源的话,使用本地锁就没办法实现资源的互斥访问了。于是,**分布式锁** 就诞生了。 + +举个例子:系统的订单服务一共部署了 3 份,都对外提供服务。用户下订单之前需要检查库存,为了防止超卖,这里需要加锁以实现对检查库存操作的同步访问。由于订单服务位于不同的 JVM 进程中,本地锁在这种情况下就没办法正常工作了。我们需要用到分布式锁,这样的话,即使多个线程不在同一个 JVM 进程中也能获取到同一把锁,进而实现共享资源的互斥访问。 + +下面是我对分布式锁画的一张示意图。 + +![分布式锁](./images/distributed-lock/distributed-lock.png) + +从图中可以看出,这些独立的进程中的线程访问共享资源是互斥的,同一时刻只有一个线程可以获取到分布式锁访问共享资源。 一个最基本的分布式锁需要满足: @@ -112,8 +130,9 @@ Redlock 算法的思想是让客户端向 Redis 集群中的多个独立的 Redi Redlock 是直接操作 Redis 节点的,并不是通过 Redis 集群操作的,这样才可以避免 Redis 集群主从切换导致的锁丢失问题。 -Redlock 实现比较复杂,性能比较差,发生时钟变迁的情况下还存在安全性隐患。《数据密集型应用系统设计》一书的作者 Martin Kleppmann 曾经专门发文怼过 Redlock,他认为这是一个很差的分布式锁实现。感兴趣的朋友可以看看[Redis 锁从面试连环炮聊到神仙打架](https://mp.weixin.qq.com/s?__biz=Mzg3NjU3NTkwMQ==&mid=2247505097&idx=1&sn=5c03cb769c4458350f4d4a321ad51f5a&source=41#wechat_redirect)这篇文章,有详细介绍到 antirez 和 Martin Kleppmann 关于 Redlock 的激烈辩论。 +Redlock 实现比较复杂,性能比较差,发生时钟变迁的情况下还存在安全性隐患。《数据密集型应用系统设计》一书的作者 Martin Kleppmann 曾经专门发文([How to do distributed locking - Martin Kleppmann - 2016](https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html))怼过 Redlock,他认为这是一个很差的分布式锁实现。感兴趣的朋友可以看看[Redis 锁从面试连环炮聊到神仙打架](https://mp.weixin.qq.com/s?__biz=Mzg3NjU3NTkwMQ==&mid=2247505097&idx=1&sn=5c03cb769c4458350f4d4a321ad51f5a&source=41#wechat_redirect)这篇文章,有详细介绍到 antirez 和 Martin Kleppmann 关于 Redlock 的激烈辩论。 实际项目中不建议使用 Redlock 算法,成本和收益不成正比。 如果不是非要实现绝对可靠的分布式锁的话,其实单机版 Redis 就完全够了,实现简单,性能也非常高。如果你必须要实现一个绝对可靠的分布式锁的话,可以基于 Zookeeper 来做,只是性能会差一些。 + diff --git a/docs/distributed-system/images/distributed-lock/distributed-lock.png b/docs/distributed-system/images/distributed-lock/distributed-lock.png new file mode 100644 index 00000000..0908f657 Binary files /dev/null and b/docs/distributed-system/images/distributed-lock/distributed-lock.png differ diff --git a/docs/distributed-system/images/distributed-lock/jvm-local-lock.png b/docs/distributed-system/images/distributed-lock/jvm-local-lock.png new file mode 100644 index 00000000..bd7ef63f Binary files /dev/null and b/docs/distributed-system/images/distributed-lock/jvm-local-lock.png differ