(求锤得锤的故事)Redis锁从面试连环炮聊到神仙打架。 (1)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: (求锤得锤的故事)Redis锁从面试连环炮聊到神仙打架。 (1)

又到了一周一次的分享时间啦,老规矩,还是先荒腔走板的聊聊生活。


有上面的图是读大学的时候,一次自行车骑行途中队友抓拍的我的照片。拍照的地方,名字叫做牛背山,一个名字很 low,实际很美的地方。


那条上山的路很难骑,超级烂路和极度变态的陡坡。真是一种折磨,是对意志力的完全考验。


在我们几近崩溃,弹尽粮绝,离山顶还有近两个多小时的时候,一个卡车司机主动要求把我们免费带到山顶。我们拒绝了。


因为同行的星哥他说了一句话:“骑行牛背山这件事情,我这辈子只会做这一次。现在的情况还不是那么糟,如果我搭车上去了,之后想起来我会有遗憾的。所以我更情愿推车。”


第二天下午山上下了一场暴风雪。于是我们几个南方孩子在这少见的雪景中肆意打闹。打雪仗,堆雪人,滑雪......


晚上雪停了之后,我看到了让我终身难忘的场景。星空,美丽到让人想哭的星空!


后来,在人生路上的很多场景中,我都会想起星哥的那句话:这件事,我这辈子只会做这一次,我不想留下遗憾。还会想起那晚璀璨的、触手可及般的星空。


坚持不住的时候再坚持一下,确实是一种难能可贵的精神。


好了,说回文章。


背景铺垫


面试的时候,不管你的简历写没写 Redis,它基本上是一个绕不过的话题。


为了引出本文要讨论的关于 Redlock 的神仙打架的问题,我们就得先通过一个面试连环炮:


1.Redis 做分布式锁的时候有需要注意的问题?


2.如果是 Redis 是单点部署的,会带来什么问题?


3.那你准备怎么解决单点问题呢?


4.集群模式下,比如主从模式,有没有什么问题呢?


5.你知道 Redis 是怎么解决集群模式也不靠谱的问题的吗?


6.那你简单的介绍一下 Redlock 吧?


7.你觉得 Redlock 有什么问题呢?


很明显,上面是一个常规的面试连环套路题。中间还可以插入很多其他的 Redis 的考察点,我这里就不做扩展了。


单点的 Redis 做分布式锁不靠谱,导致了基于 Redis 集群模式的分布式锁解决方案的出现。


基于 Redis 集群模式的分布式锁解决方案还是不靠谱,Redis 的作者提出了 Redlock 的解决方案。


Redis 作者提出的 Redlock 的解决方案,另一位分布式系统的大神觉得它不靠谱,于是他们之间开始了 battle。


基于这场 battle,又引发了更多的讨论。


这场 battle 难分伯仲,没有最后的赢家。如果一定要选出谁是最大的赢家的话,那一定是吃瓜网友。因为对于吃瓜网友来说(比如我),可以从两位大神的交锋中学习到很多东西。


让你深刻的体会到:看起来那么无懈可击的想法,细细推敲之下,并不是那么天衣无缝。


所以本文就按照下面的五个模块展开讲述。


先来一波劝退:本文近1.2w字,谨慎观看。看不下去不要紧,点个赞就是对于我最大的鼓励。奥利给!


单点Redis


按照我的经验,当面试聊到 Redis 的时候,百分之 90 的朋友都会说**:Redis在我们的项目中是用来做热点数据缓存的**。


然后百分之百的面试官都会问:


Redis除了拿来做缓存,你还见过基于Redis的什么用法?


接下来百分之 80 的朋友都会说到:我们还用 Redis 做过分布式锁。


(当然, Redis 除了缓存、分布式锁之外还有非常非常多的奇技淫巧,不是本文重点,大家有兴趣的可以自己去了解一下。)


那么面试官就会接着说:


那你给我描述(或者写一下伪代码)基于Redis的加锁和释放锁的细节吧。


注意面试官这里说的是加锁和释放锁的细节,魔鬼都在细节里。


问这个问题面试官无非是想要听到下面几个关键点:


关键点一:原子命令加锁。因为有的“年久失修”的文章中对于 Redis 的加锁操作是先set key,再设置 key 的过期时间。这样写的根本原因是在早期的 Redis 版本中并不支持原子命令加锁的操作。不是原子操作会带来什么问题,就不用我说了吧?如果你不知道,你先回去等通知吧。


而在 2.6.12 版本后,可以通过向 Redis 发送下面的命令,实现原子性的加锁操作:


SET key random_value NX PX 30000


关键点二:设置值的时候,放的是random_value。而不是你随便扔个“OK”进去。


先解释一下上面的命令中的几个参数的含义:


random_value:是由客户端生成的一个随机字符串,它要保证在足够长的一段时间内在所有客户端的所有获取锁的请求中都是唯一的。


NX:表示只有当要设置的 key 值不存在的时候才能 set 成功。这保证了只有第一个请求的客户端才能获得锁,而其它客户端在锁被释放之前都无法获得锁。


PX 30000:表示这个锁有一个 30 秒的自动过期时间。当然,这里 30 秒只是一个例子,客户端可以选择合适的过期时间。


再解释一下为什么 value 需要设置为一个随机字符串。这也是第三个关键点。


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


(基本上能答到这几个关键点,面试官也就会进入下一个问题了。常规热身送分题呀,朋友们,得记住了。)


集群模式


面试官就会接着问了:


经过刚刚的讨论,我们已经有较好的方法获取锁和释放锁。基于Redis单实例,假设这个单实例总是可用,这种方法已经足够安全。如果这个Redis节点挂掉了呢?


到这个问题其实可以直接聊到 Redlock 了。但是你别慌啊,为了展示你丰富的知识储备(疯狂的刷题准备),你得先自己聊一聊 Redis 的集群,你可以这样去说:


为了避免节点挂掉导致的问题,我们可以采用Redis集群的方法来实现Redis的高可用。

Redis集群方式共有三种:主从模式,哨兵模式,cluster(集群)模式


其中主从模式会保证数据在从节点还有一份,但是主节点挂了之后,需要手动把从节点切换为主节点。它非常简单,但是在实际的生产环境中是很少使用的。


哨兵模式就是主从模式的升级版,该模式下会对响应异常的主节点进行主观下线或者客观下线的操作,并进行主从切换。它可以保证高可用。


cluster (集群)模式保证的是高并发,整个集群分担所有数据,不同的 key 会放到不同的 Redis 中。每个 Redis 对应一部分的槽。


(上面三种模式也是面试重点,可以说很多道道出来,由于不是本文重点就不详细描述了。主要表达的意思是你得在面试的时候遇到相关问题,需要展示自己是知道这些东西的,都是面试的套路。)


在上面描述的集群模式下还是会出现一个问题,由于节点之间是采用异步通信的方式。如果刚刚在 Master 节点上加了锁,但是数据还没被同步到 Salve。这时 Master 节点挂了,它上面的锁就没了,等新的 Master 出来后(主从模式的手动切换或者哨兵模式的一次 failover 的过程),就可以再次获取同样的锁,出现一把锁被拿到了两次的场景。


锁都被拿了两次了,也就不满足安全性了。一个安全的锁,不管是不是分布式的,在任意一个时刻,都只有一个客户端持有。

相关实践学习
基于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
目录
相关文章
|
19天前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
2月前
|
NoSQL Java API
美团面试:Redis锁如何续期?Redis锁超时,任务没完怎么办?
在40岁老架构师尼恩的读者交流群中,近期有小伙伴在面试一线互联网企业时遇到了关于Redis分布式锁过期及自动续期的问题。尼恩对此进行了系统化的梳理,介绍了两种核心解决方案:一是通过增加版本号实现乐观锁,二是利用watch dog自动续期机制。后者通过后台线程定期检查锁的状态并在必要时延长锁的过期时间,确保锁不会因超时而意外释放。尼恩还分享了详细的代码实现和原理分析,帮助读者深入理解并掌握这些技术点,以便在面试中自信应对相关问题。更多技术细节和面试准备资料可在尼恩的技术文章和《尼恩Java面试宝典》中获取。
美团面试:Redis锁如何续期?Redis锁超时,任务没完怎么办?
|
2月前
|
NoSQL 算法 Redis
Redis面试篇
Redis面试篇
46 5
|
1月前
|
存储 NoSQL Redis
Redis常见面试题:ZSet底层数据结构,SDS、压缩列表ZipList、跳表SkipList
String类型底层数据结构,List类型全面解析,ZSet底层数据结构;简单动态字符串SDS、压缩列表ZipList、哈希表、跳表SkipList、整数数组IntSet
|
2月前
|
存储 Kubernetes 架构师
阿里面试:JVM 锁内存 是怎么变化的? JVM 锁的膨胀过程 ?
尼恩,一位经验丰富的40岁老架构师,通过其读者交流群分享了一系列关于JVM锁的深度解析,包括偏向锁、轻量级锁、自旋锁和重量级锁的概念、内存结构变化及锁膨胀流程。这些内容不仅帮助群内的小伙伴们顺利通过了多家一线互联网企业的面试,还整理成了《尼恩Java面试宝典》等技术资料,助力更多开发者提升技术水平,实现职业逆袭。尼恩强调,掌握这些核心知识点不仅能提高面试成功率,还能在实际工作中更好地应对高并发场景下的性能优化问题。
|
2月前
|
缓存 NoSQL 算法
面试题:Redis如何实现分布式锁!
面试题:Redis如何实现分布式锁!
|
2月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(一)
数据的存储--Redis缓存存储(一)
83 1
|
2月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
78 6
|
20天前
|
存储 缓存 NoSQL
【赵渝强老师】基于Redis的旁路缓存架构
本文介绍了引入缓存后的系统架构,通过缓存可以提升访问性能、降低网络拥堵、减轻服务负载和增强可扩展性。文中提供了相关图片和视频讲解,并讨论了数据库读写分离、分库分表等方法来减轻数据库压力。同时,文章也指出了缓存可能带来的复杂度增加、成本提高和数据一致性问题。
【赵渝强老师】基于Redis的旁路缓存架构
|
13天前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
33 5