篇幅太长看着也累,尝试分成多个小章节,每天进步一点点。
分布式锁系列介绍
分布式锁系列内容规划如下,本篇是第 1 篇:
- 《分布式锁上-初探》(本篇)
- 《分布式锁中-基于 Zookeeper 的实现是怎样》
- 《分布式锁中-基于 etcd 的实现很优雅》
- 《分布式锁中-基于 Redis 的实现需避坑 - Jedis 篇》
- 《分布式锁中-基于 Redis 的实现很多样 - Redission 篇》(写作中)
- 《分布式锁中-基于 MySQL 的实现 - 有得用就好》(写作中)
- 《分布式锁中-多维度的对比各种分布式锁实现》(写作中)
- 《分布式锁下-分布式锁客户端的抽象、适配与加固》(写作中)
1 分布式锁产生的背景
很多时候,我们会遇到在JVM实例内多个线程要竞争使用具有排它性的共享资源,JVM中提供了synchronized 、 JUC中提供的xxxLock 使用这些锁可以方便我们实现对临界资源的互斥使用,这种使用锁的方式是一种显式同步的方式,来控制线程之间操作发生相对顺序的机制,除了使用这种方式还有另外一种隐式同步方式,即消息传递;但大家似乎对显示的使用锁的方式更为熟悉一些。
基于各种因素现在的系统大多已演进为分布式的架构,正如实例内多线程要互斥使用临界资源,分布式情况下多实例之间也会存在需要排它的使用共享资源,这个问题就是分布式互斥问题。虽然大佬Lamport 在论文 《Time, clocks, and the ordering of events in a distributed system》中早就证明了使用状态机(如共识算法)就能够去中心化解决多进程互斥问题,但我们还是会更偏向使用分布式锁,原因大概有以下3点:
- 使用分布式锁服务更易于保持现有程序的结构
- 程序员更熟悉用加锁的方式来同步访问资源
- 共识算法可能会要求客户端运行在更多的服务器中以满足共识算法需求,而实际仅满足客户端功能性的需求则不需要这么多服务器
概括来说,分布式锁更易用、也更节省资源
2 使用分布式锁的目的
使用分布式锁的目的主要有两种,分别是:
- 效率(Efficiency):通过锁来避免多次做重复的工作,计算重复的内容等等。这种场景下即便偶然出现多个用户同时持有锁,并同时与资源服务发生交互,也是可以忍受的。
- 正确性(Correctness):也就是文章标题所说的“安全”,我们希望资源服务在锁的保护下能够做“正确”的事。更严谨的说,我们希望任一时刻,只有一个用户能够访问资源服务,而且即便锁在该用户在与资源服务交互的中途过期,也不至于破坏资源服务的一致性。
3 分布式锁的功能特点
那么一个分布式锁应具备哪些功能特点呢?
- 互斥性:在同一时刻,只有一个客户端能持有锁
- 安全性:避免死锁,如果某个客户端获得锁之后处理时间超过最大约定时间,或者持锁期间内发生了故障导致无法主动释放锁,其持有的锁也能够被其他机制正确释放,并保证后续其它客户端也能加锁,整个处理流程继续正常执行。
- 可用性:也被称作容错性,分布式锁需要有高可用能力,避免单点故障,当提供锁的服务节点故障(宕机)时不影响服务运行,这里有两种模式:一种是分布式锁服务自身具备集群模式,遇到故障能自动切换选主;另一种是客户端向多个独立的锁服务发起请求,当某个锁服务故障时仍然可以从其他锁服务读取到锁信息(Redlock)
- 可重入性:对同一个锁,加锁和解锁必须是同一个进程,即不能把其他进程持有的锁给释放了。
- 高效灵活:加锁、解锁的速度要快;支持阻塞和非阻塞;支持公平锁和非公平锁。
4 多视角下的分布式锁
通过不同视角,可以从多维度充分了解各种分布式锁的实现差异
视角1:
轮询类:基于数据库和基于 Redis 实现的分布式锁,这类实现需要客户端不停反复请求锁服务查看是否能够获取到锁; 监听类:基于 ZooKeeper 或 etcd 实现的分布式锁,这类实现客户端只需监听(watch) 某个 key,当锁可用时锁服务会通知客户端,无需客户端不停请求锁服务。
视角2:
基于数据库实现的分布式锁:采用乐观锁、悲观锁或者基于主键唯一约束实现 基于分布式缓存实现分布式锁:Redis 和基于 Redis 的 RedLock(Redisson) 基于分布式一致性算法实现的分布式锁:ZooKeeper、 Etcd
视角3:
Martin Kleppmann 在个人博客中发了一篇文章 How to do distributed locking,其中涉及了大量对 Redlock 算法安全性的质疑,Salvatore Sanfilippo(Redis 的创始人,也是这里 Redlock 算法的作者)随后发表 Is Redlock safe? 回应这些质疑,这篇文章总结了这两篇文章讨论的重点和我对这些问题的想法。
文末的补充(请关注,莫错过)
如果这篇文章对您有所帮助,或者有所启发的话,帮忙扫描下发二维码关注一下,关注公众号:架构染色,进行交流和学习。您的支持是我坚持写作最大的动力。