分布式系统面试总结:3、分布式锁(和本地锁的区别、特点、常见实现方案)
仅供自学回顾使用,请支持javaGuide原版书籍。
本篇文章涉及到的分布式锁,在本人其他文章中也有涉及。
《JUC:三、两阶段终止模式、死锁的jconsole检测、乐观锁(版本号机制+CAS实现)+悲观锁》:https://blog.csdn.net/zhiaidaidai/article/details/142862002
《redis:四、双写一致性的原理和解决方案(延时双删、分布式锁)》:https://blog.csdn.net/zhiaidaidai/article/details/135030539
必看⭐⭐⭐:《redis:六、setnx获取锁、Lua脚本释放锁、基于redisson的分布式锁(看门狗机制、主从一致性、红锁)》:https://blog.csdn.net/zhiaidaidai/article/details/135064906
1.本地锁和分布式锁
对于单机多线程来说,在 Java 中,我们通常使用 synchronized 关键字这类 JDK 自带的 本地锁 来控制一个 JVM 进程内的多个线程对本地共享资源的访问,如下:
分布式系统下,不同的服务/客户端通常运行在独立的 JVM 进程上。如果多个 JVM 进程共享同一份资源的话,使用本地锁就没办法实现资源的互斥访问了。于是,分布式锁 就诞生了。
2.分布式锁的特点
一个最基本的分布式锁需要满足:
互斥
:任意一个时刻,锁只能被一个线程持有。高可用
:锁服务是高可用的,当一个锁服务出现问题,能够自动切换到另外一个锁服务。并且,即使客户端的释放锁的代码逻辑出现问题,锁最终一定还是会被释放,不会影响其他线程对共享资源的访问。这一般是通过超时机制实现的。可重入
:一个节点获取了锁之后,还可以再次获取锁。
除了上面这三个基本条件之外,一个好的分布式锁还需要满足下面这些条件:
高性能
:获取和释放锁的操作应该快速完成,并且不应该对整个系统的性能造成过大影响。非阻塞
:如果获取不到锁,不能无限期等待,避免对系统正常运行造成影响。
3.常见分布式锁实现方案
常见分布式锁实现方案如下:
- 基于关系型数据库比如 MySQL 实现分布式锁。
- 一般是通过唯一索引或者排他锁实现。
- 一般不会使用这种方式,问题太多比如性能太差、不具备锁失效机制。
- 基于分布式协调服务 ZooKeeper 实现分布式锁。
- 基于分布式键值存储系统比如 Redis 、Etcd 实现分布式锁。
关系型数据库的方式基于 ZooKeeper 或者 Redis 实现分布式锁这两种实现方式要用的更多一些。