面试时遇到『看门狗』脖子上挂着『时间轮』,我就问你怕不怕? (1)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 面试时遇到『看门狗』脖子上挂着『时间轮』,我就问你怕不怕? (1)

荒腔走板聊生活


大家好,一周的时间过的飞快,转眼间又到周末了。


老规矩,还是本号特色,先是荒腔走板的聊聊生活。


上面的图片是我在一次跑步的过程中拍的,一只狗子。可以看到图片中还有一个轨迹图,也是一只狗子。


这个轨迹图全长21km,刚好是一个半马的距离,而且一路上会穿过北海、什刹海、南锣鼓巷、雍和宫、地坛、鼓楼大街、德胜门这些比较知名的景点。我个人非常喜欢这个路线,在北京的时候跑过好几次。


如果你在北京,也有去跑一跑这个轨迹然后发朋友圈装逼的想法,可以在关注公众号后,在后台回复“狗子跑”。我会把具体的路线图回复给你。


最近由于疫情,距离上次跑步已经过了很久很久了,虽然公司有跑步机,但是我一向不太习惯在跑步机上跑。


这周成都基本上解禁了,小区里面跑步的人也慢慢出来了,所以我决定这篇文章写完后,一定要出去跑个至少10km,准备开启这个夏天,毕竟一到夏天,我不经意间漏出的腹肌也该出来活动活动了。


好了,说回文章。


面试后的复盘非常重要


之前写了《求锤得锤之神仙打架》这篇文章,在长发哥出锤这一小节中,里面有写到这样一段话:


于是就有读者来问了:老哥,看门狗介绍一下呗。面试的时候被问到了,没有回答上来。

听到这个问题我脑海里首先浮现出了几个问题:


1.你面试被问到,没有答上来,然后呢?


2.面试结束之后你没有进行面试的复盘吗?


3.对于自己没有回答上来的问题,没有去进行探索吗?


甚至你都忘记了当时你的面试题,只是看到我文章的时候,突然想起:哦,这题我之前遇到过,没有解决。


这个方式是不对的,朋友。


一次面试是一场技术的交锋,所以面试之后的复盘非常非常的重要,面试结束后的第一件事情就应该是回顾整个面试过程,看看在整个面试的过程中,哪些地方是自己知道但是没有说清楚的,哪些地方是自己应该知道但是确实不知道,需要去提升的。


然后立刻、马上、当即在手机标签或者随身笔记上记录下复盘后自己的总结出来的关键点。


这些关键点可以是表现的好的地方,但是更多的应该是需要提升的地方。


也许你也在网上看到过这个套路:面试的过程中有几个问题没有回答上来,最后面试官说你先回去等通知吧。于是面试结束后,你对于没有回答上来的问题进行了学习,然后把自己的学习总结发给面试官。面试官一看,哟,这小伙可以啊,学习能力还不错。


然后就真的通知你准备进行下一轮面试吧。


这招我没用过,但是这个套路,传递的思想就是:在自己领域范围内,不懂的问题,遇到了,你得主动去解决。


面试后的复盘,非常的重要。


复盘过程中的想法形成文字,保留下来,非常非常的重要。


形成文字了,还可以分享出去,帮助后来人。


好了,既然读者问了这个问题,我就稍微扩展一下,把我自己知道的都分享一下。


先看示例代码


Redisson 分布式锁可能大多数朋友都用过。先上个代码给大家看看是怎么用的。


看到这几行代码,你先别往下看,你先想一想,和你自己造的轮子比起来有什么非常明显不一样的地方?


我给大家分享一下我第一次用 Redission 做分布式锁的时候遇到的两个非常直观的疑问吧。


1.value去哪里了?


2.过期时间去哪里了?


之前说过,如果是我们自己造轮子,基于 Redis 做分布式锁的话,需要向 Redis 发一条下面的命令:


SET key random_value NX PX 3000


而在我们上面的示例代码中,为什么只有 key 没有 value 呢?


我们知道 value 是必须要有的。还记得《求锤得锤之神仙打架》这篇文章里面说的,当面试官问:


你给我讲一讲基于Redis的加锁和释放锁的细节吧。


我们从三个关键点中去回答:


1.原子命令加锁。


2.设置值的时候,放的是random_value。


3.value 的值设置为随机数主要是为了更安全的释放锁,释放锁的时候需要检查 key 是否存在,且 key 对应的值是否和我指定的值一样,是一样的才能释放锁。所以可以看到这里有获取、判断、删除三个操作,为了保障原子性,我们需要用 lua 脚本。


所以,这个 value 是非常重要的。


另外,第 3 步,释放锁的时候为什么需要 lua 脚本,也有读者问过,其实这事几句话就能说清楚,所以我在这里插播一下:


你看这三个操作:获取、判断、删除。


获取操作,只读不写,没有任何问题。问题就出在判断和删除之间。如果不是原子操作,出现了下面的情况:


1.线程 A 在判断了 value 是自己放进去的,在执行 key 删除操作之前,程序 GC 导致了 STW。


2.STW 期间线程 A 的锁虽然没有执行删除操作,但是由于时间到期被 redis 释放了。


3.STW 之后,在线程 A 执行删除操作之前,线程 B 加了同样 key 的锁。


4.结果你猜怎么着?线程 A 把线程 B 加的锁删除了。这就出问题了。


为什么 lua 脚本可以解决这个问题呢?


因为 lua 脚本的执行是原子性的,再加上 Redis 执行命令是单线程的,所以在 lua 脚本执行完之前,其他的命令都得等着。就不会出现上面说的情况了。


第二个问题是过期时间去哪里了呢?


看上面的加锁代码,像是没有设置过期时间似的。


我们先说说没有过期时间的问题是什么。很明显嘛,容易造成死锁。


加锁操作的服务器,在没有执行释放锁操作之前,服务器崩了。


哦豁,喜提死锁一把。


value去哪了?


对于这个问题,首先我们需要确定的是,value一定是有的。


当我们自己放 value 的时候,一般就是搞个随机值,往里面一塞就完事了。


另外,我见过网上有些分析 Redis 分布式锁的文章里面 value 直接扔个 OK 进去。前面我们说过,这是不对啊,朋友们。要注意辨别。


用 Redssion 时,我们知道这个 key 肯定是框架帮我们生成了。所以我们只需要去源码中验证我们的想法即可


但是,先别慌,我们还有一个更加简单的验证方法:程序跑起来,然后去 Redis 里面看一眼不就完事了?


看了一眼后发现,不错哦,不仅验证了我们的想法,还有意外收获呢。


意外收获一:我们看到了 TTL:25 说明虽然我们没用设置过期时间,但是框架帮我们把过期时间设置好了。这部分在这一小节中先按下不表,等下一小节详细描述。


意外收获二:可以看到我们放进去的 why 是一个 Hash 类型。并不是我们常用的 String 类型。


很明显,key 是 UUID:1,这个 1 是什么含义呢?


为什么要用 Hash 类型,而不用 String 类型呢?


我们带着这两个疑问去看一眼源码。


注意本文中的 Redssion 的 Maven 版本为 3.12.3。


Redssion 的源码非常好 Debug,我建议你自己实际操作一遍。


首先 lock 操作会调用到这个方法:


org.redisson.RedissonLock#lock(long, java.util.concurrent.TimeUnit, boolean)

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
前端开发 芯片
【芯片前端】同步FIFO的一个小的延伸——一会加一会减得计数器怎么写
【芯片前端】同步FIFO的一个小的延伸——一会加一会减得计数器怎么写
|
存储 NoSQL
3.10.0-693.5.2内核nfs客户端租约过期挂死问题分析
## 现象 1. 边缘存储两个节点fileserver,glance挂载物理机上的挂载点均出现挂住无法访问 2. 从客户端抓包看,客户端内核间隔5s向服务端发送renew租约请求,服务端返回NFS4ERR_EXPIRED,即租约过期错误,从抓包现象看客户端一直向服务端发送相同的clientid renew请求,服务端一直返回租约过期错误,导致挂载点无法恢复 ![](https://ata2-img
1670 1
3.10.0-693.5.2内核nfs客户端租约过期挂死问题分析
|
监控 网络协议 Dubbo
开工第一天,这个超时问题把我干趴下了!
开工第一天,这个超时问题把我干趴下了!
|
IDE Java 开发工具
震惊!这样终止线程,竟然会导致服务宕机?(上)
震惊!这样终止线程,竟然会导致服务宕机?(上)
138 0
震惊!这样终止线程,竟然会导致服务宕机?(上)
|
NoSQL 安全 Linux
面试时遇到『看门狗』脖子上挂着『时间轮』,我就问你怕不怕? (3)
面试时遇到『看门狗』脖子上挂着『时间轮』,我就问你怕不怕? (3)
266 0
|
算法 NoSQL 程序员
面试时遇到『看门狗』脖子上挂着『时间轮』,我就问你怕不怕? (2)
面试时遇到『看门狗』脖子上挂着『时间轮』,我就问你怕不怕? (2)
196 0
|
程序员
空闲时间请大家不要接私活,要提升自己!
  现在社会,有很多人都在利用个人时间兼职赚钱,程序员俗称“接私活”,其他行业称作兼职,比如下了班出去跑滴滴,周末兼职抢单送外卖等等,都是普通人很常见的兼职方式。   甚至很多技术同行,我听说也有周末去跑滴滴和送外卖的,我觉得很不可思议,然而我的观点是如果你想成为成功人士,高收入人群那么你不应该去做兼职,不要把你宝贵的时间,浪费在兼职上。   简单经济学分析   涉及到收入,文字洗脑显得很空洞了就,那么今天我给你来一个简单的经济学论调。   我们看一个案例,李嘉诚是香港首富,但是李嘉诚会亲自修剪自家的草坪吗?除非某一天他想体验一下劳动乐趣什么的,否则一定是请人来修剪草坪。
152 0
|
安全 Java
震惊!这样终止线程,竟然会导致服务宕机?(下)
震惊!这样终止线程,竟然会导致服务宕机?(下)
192 0
|
Web App开发 SQL Java
艾伟_转载:一次挂死(hang)的处理过程及经验
前言:        CPU占用率低,内存还有许多空余,但网站无法响应,这就是网站挂死,通常也叫做hang。这种情况对于我这样既是CEO,又是CTO,还兼职扫地洗碗的个人站长来说根本就是家常便饭。以下是一次处理hang的经验及总结,前后用了一个月,不仅涉及程序排查,数据库优化,还有硬件升级的苦恼。
1653 0