面试官:Redis分布式锁超时了,任务还没执行完怎么办?

13,240 阅读5分钟

图片

做一个单纯的程序汪,分享干货,聊聊人生。

微信公众号:后端架构进阶

关注我发现更多的干货,微服务、Spring源码、JVM、SpringCloud Alibaba、K8S等。

如果你觉得本文对你有帮助,麻烦给我点个赞,感谢支持!

历史文章汇总:包含Netty、源码、并发、JVM等

今天主要分享的是面试中常见的redis的一些面试内容。如果你正好需要刚好可以帮你回顾一下,如果不需要可以收藏起来后面用到的时候翻出来回顾。

一、背景

面试官:你们项目中有使用分布式锁么?

我:有使用。

面试官:你们使用分布式锁主要是为了干啥?

我:多节点并发访问同一份数据的时候,防止造成脏数据。

面试官:都有哪些方案实现分布式锁?你们用的是哪一种?

我:有基于zk的临时顺序节点的方案,有redis的setnx和指定expire超时时间的方案。

面试官:你们是用哪种方案呢?

我:用的是redis的一个封装组件Redisson。

面试官:你们redis是用的哪种集群模式?

我:用的是redis的cluster集群模式。

面试官:Redisson可以配置哪些模式?

我:单节点模式、cluster模式、哨兵模式

面试官:那分布式锁的锁超时时间是怎么配置的?

我:这个超时时间需要根据业务场景进行压测然后根据压测结果进行评估,在压测结果上进行稍微放大1~2倍。

面试官:那假如分布式锁设置的超时时间是2s,但是2s内还没执行完成,锁自动释放了,这种怎么处理呢?

我:这个,有点记不清了。

面试官:好的。你们redis cluster集群模式中,如果主挂了怎么办?

我:我们是三主三从的集群模式,如果半数以上主节点与故障主节点通信超过,认为当前该主节点挂掉,主下面的从就会变为主。如果主下面没有从,那么集群就会进入fail状态。从节点就是主节点的备份。

面试官:redis的持久化机制有几种,分别有什么优缺点?

我:redis的持久化分为:RDB和AOF,一种是快照,一种是追加。快照的话是一段时间进行数据的备份,追加是只要有指令执行,就记录记录指令信息。后面可以根据指令进行数据的恢复。

快照模式如果挂了的话很有可能在快照期间数据丢失了,优点是恢复数据比较快,镜像的话恢复会比较慢,优点是数据数据存的比较全,配置好持久化策略可以做到数据完全不丢失。

面试官:那你们是怎么用的?

我:我们是两种都用,定期备份数据。挂了之后方便快速恢复同时保证了数据的完整性。

真是打破砂锅问到底啊,兄弟集美们,夺命连环十八问。

不过一码归一码,还是让我回忆起很多知识。也顺带总结起来,下次遇到这块问题的时候也不至于啥都说不出来。

接下来,把Redisson在锁超时后业务还没执行完成的情况细聊下。

二、Redisson锁超时看门狗机制

Redisson的宗旨是促进使用者对 Redis 的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。

先上Github地址,中文文档,贼6。

Redisson中文文档 github.com/redisson/re…

接下来主要分析:如果锁已经超时了,但是线程还没执行完任务该如何处理?

可重入锁(Reentrant Lock)

基于Redis的Redisson分布式可重入锁RLock Java对象实现了java.util.concurrent.locks.Lock接口。同时还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。

RLock lock = redisson.getLock("anyLock");
//最常见的使用方法
lock.lock();

大家都知道,如果负责储存这个分布式锁的Redisson节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。

为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。

默认情况下,看门狗的检查锁的超时时间是30秒钟,

也可以通过修改Config.lockWatchdogTimeout 来另行指定。

另外Redisson还通过加锁的方法提供了 leaseTime 的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

// 加锁以后10秒钟自动解锁
// 无需调用unlock方法手动解锁
lock.lock(10, TimeUnit.SECONDS);

// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
   try {
     ...
   } finally {
       lock.unlock();
   }
}

三、拓展:

Redisson同时还为分布式锁提供了异步执行的相关方法:

RLock lock = redisson.getLock("anyLock");
lock.lockAsync();
lock.lockAsync(10, TimeUnit.SECONDS);
Future<Boolean> res = lock.tryLockAsync(100, 10, TimeUnit.SECONDS);

RLock对象完全符合Java的Lock规范。也就是说只有拥有锁的进程才能解锁,其他进程解锁则会抛出 IllegalMonitorStateException 错误。但是如果遇到需要其他进程也能解锁的情况,请使用分布式信号量 Semaphore 对象。

四、总结

以上就是今日的内容总结和分享,感谢各位大佬的 点赞关注收藏

微信公众号:后端架构进阶

更多文章正在赶来,喜欢记得给我点个 👍 ,感谢支持!

公众号文章同步更新!关注我,不迷路!