分布式锁面试常考题
分布式锁
什么是分布式锁
分布式锁是在分布式环境下实现锁的机制。在一个分布式系统中,如果多个进程需要对同一资源进行操作,为了保证数据的一致性和防止数据竞争,就需要使用分布式锁。
为什么要使用分布式锁
- 单机版和分布式锁都是为了保证数据的一致性和防止并发冲突,但是它们适用的场景不同。
- 单机锁主要用于单个系统或者服务,当多个线程并发访问同一份资源时,通过单机锁可以保证在同一时间只有一个线程能够访问该资源,从而保证数据的一致性。
- 但是,当系统扩展到分布式环境,即多个系统或服务需要访问同一份资源时,单机锁就无法满足需求了,因为单机锁只能在同一台机器上锁住资源,无法跨节点访问。
- 分布式锁则是为了解决这个问题而出现的。在分布式环境下,多个系统或服务可能在不同的机器上运行,它们可能需要同时访问和修改同一份数据,如果没有合适的并发访问控制机制,就可能导致数据的不一致性。分布式锁可以跨节点对资源进行加锁,保证在同一个时间只有一个系统或服务能够访问该资源,从而保证数据的一致性。
- 因此,当系统从单机版到分布式环境时,就需要使用分布式锁来代替单机锁,以保证数据的一致性和防止并发冲突。
分布式锁实现的方式有几种?
常见的实现方式有:
- 基于数据库的分布式锁,这种实现比较简单,但是性能比较低。
- 基于Redis实现的分布式锁,这种实现性能高,但是存在因为主从同步导致key丢失的安全问题。
- 基于Zookeeper的分布式锁,实现性能稍弱于redis,可靠性安全性较高。
- 基于Etcd的分布式锁,性能不错,API使用简单。
Redis实现分布式锁怎么实现的?
首先实现分布式锁需要满足几个特点
-
互斥性
- Setnx
-
原子性
- lua脚本
-
锁超时,防死锁
- 过期时间
-
锁误删(客户端A设置锁,客户端B执行del,把A删除了,可通过设置对lock的的value进行判断)
- 客户端uuid
-
可重入性
- hash数据结构存储(外层key 锁名称,内层的value进行++,当--到0时删除)
-
支持阻塞和非阻塞
- 设置锁超时时间
-
支持公平锁和非公平锁
- 利用redis的list数据结构,用于等待锁线程排队,按照先进先出
Redisson实现分布式锁源码
以下是Redisson实现分布式锁的基本流程:
- 获取锁:当一个线程请求获取锁时,Redisson内部会构建一个Redis的lua脚本,然后发送给Redis服务器执行。这个ua脚本主要做两件事情:一是尝试设置一个key(锁的名字)是如果设置成功,就给这个key设置一个过期时间。这两个操作是原子的。如果设置key成功,表示获取锁成功,如果设置key失败(key已存在),表示获取锁失败。
- 锁续期:为了防止线程在获取锁后,因为处理业务逻辑时间过长而导致锁自动过期,Redisson内部会启动一个定时任务,定期给锁续期。
- 释放锁::当线程壳成愿务处理册:会通过Redis的lua脚本来尝试释放锁。这个lua脚本主要做两件事情:一是获取key的值,二是如果值与预期相同,就删除这个key。这两个操作也是原子的。这样可以保证只有获取锁的线程才能释放这个锁。
以上就是Redisson实现分布式锁的基本流程。在实际使用中,Redisson还提供了公平锁、读写锁、多锁、红锁等高级功能,可以满足各种复杂的分布式锁需求。
MySQL实现分布式锁怎样实现?
- 利用MySQL悲观锁
- 利用MySQL唯一索引
Etcd实现分布式锁怎样实现?
- prefix前缀查询
- revision机制
- 租约机制