面试题答案
一键面试数据结构设计
- 锁标识:使用一个唯一的字符串作为锁的标识,例如业务相关的键名。
- 持有锁的客户端标识:每个尝试获取锁的客户端会生成一个唯一ID,作为锁持有者的标识,防止误解锁。
- 过期时间:为锁设置一个初始过期时间,以确保在异常情况下锁能自动释放。在Redis中,可以使用
SET key value EX seconds NX
命令来设置带有过期时间的锁。
续期逻辑
- 客户端本地定时器:持有锁的客户端启动一个本地定时器,定时任务时间设置为小于锁过期时间的一半(如过期时间为30秒,定时器设为10秒)。当定时器触发时,客户端向Redis发送续期命令。
- 续期命令:客户端使用
SET key value EX new_seconds NX
命令进行续期,其中new_seconds
为新的过期时间。因为持有锁的客户端标识不变,并且使用NX
选项,只有当锁仍然存在且持有者是当前客户端时才能续期成功。 - 异步续期:为了避免续期操作影响主线程性能,可以使用异步任务或线程来执行续期逻辑。例如在Java中使用
CompletableFuture
或线程池。
故障恢复策略
- Redis节点故障
- 主从复制:使用Redis的主从复制机制,当主节点故障时,从节点可以晋升为主节点,保证服务的可用性。但在主从切换过程中,可能存在数据不一致的问题。为了解决这个问题,可以使用Redlock算法。
- Redlock算法:使用多个独立的Redis节点(至少5个),客户端在大部分节点(至少3个)上成功获取锁才认为获取锁成功。在续期时,同样需要在大部分节点上执行续期操作。当某个节点故障时,只要大部分节点正常,锁服务仍然可用。
- 网络分区
- 客户端重试:当客户端检测到网络分区导致续期失败时,开始重试机制。设置一个最大重试次数和重试间隔,逐步增加重试间隔,避免短时间内大量无效重试。
- 自适应调整:根据网络状况动态调整锁的过期时间和续期策略。例如,在网络不稳定时适当延长锁的过期时间,减少续期频率,降低网络压力。