最近整理一份关于Redis常见面试题的,也会根据自己的经验, 标注一些出现的概率,最高5颗★出现的概率最高。比如这样:

Redis 最适合的场景, 可以简单的说说吗?
出现概率: ★★★★

整体目录大概如下:

目录

  • 一、Redis基础知识

    • 1、什么是 Redis, 有哪些优缺点?
    • 2、Redis 最适合的场景, 可以简单的说说吗?
    • 3、Redis 相比 Memcached 有哪些优势?
    • 4、一个字符串类型的值能存储最大容量是多少?
    • 5、Redis 读写分离
  • 二、数据结构
    • 1、Redis的数据类型有哪些?
    • 2、说说 Redis 哈希槽的概念?
    • 3、Hash如何实现O(1)的查询和设置速度, 以及扩容原理
    • 4、布隆过滤器
  • 三、事务
    • 1、怎么理解 Redis 事务?
    • 2、Redis事务执行过程
    • 3、Redis事务的一些使用场景
    • 4、Redis事务与Redis pipeline的区别
    • 5、集群模式下Redis事务如何保证原子性
  • 四、Redis数据持久化
    • 1、为什么 Redis 需要把所有数据放到内存中?
    • 2、Redis如何做持久化的?
    • 3、Redis key 的过期时间和永久有效分别怎么设置?
  • 五、Redis集群
    • 1、Redis 是单进程单线程的?
    • 2、是否使用过 Redis 集群,集群的原理是什么?
    • 3、可以简单说说你对Redis Sentinel的理解
    • 4、Redis Sentinal和Redis Cluster的区别
    • 5、Redis 的同步机制了解么?
    • 6、Redis 集群最大节点个数是多少?
  • 六、Redis淘汰策略
    • 1、Redis过期键的删除策略?
    • 2、你可以简单聊聊Redis内存淘汰机制(回收策略)
  • 七、Redis分布式锁
    • 1、你知道实现实现分布式锁有哪些方案?
  • 八、Redis缓存问题
    • 1、Redis缓存雪崩
    • 2、Redis缓存击穿
    • 3、Redis缓存穿透
    • 4、缓存预热
    • 5、缓存降级
  • 九、运维和部署
    • 1、Redis 如何设置密码及验证密码?
    • 2、Redis 如何做内存优化?
  • 你知道实现实现分布式锁有哪些方案?

#你知道实现实现分布式锁有哪些方案?

出现概率: ★★★★★

分布式锁无论是在平时开发中还是面试中都是很常见的问题, 所以建议自己多梳理一下。知其然, 且知其所以然。

1、在开始之前首先要知道什么是分布式锁 ?

分布式锁其实就是控制分布式系统不同进程共同访问共享资源的一种锁的实现。如果不同的系统或同一个系统的不同主机之间共享了某个临界资源,往往需要互斥来防止彼此干扰,以保证一致性。

在分布式锁方面, Redis有广泛应用, 日常开发中分布式锁的一些常见常见有秒杀下单、抢红包等等。

2、分布式锁的特点如下:

  • 互斥性:和我们本地锁一样互斥性是最基本,但是分布式锁需要保证在不同节点的不同线程的互斥。
  • 可重入性:同一个节点上的同一个线程如果获取了锁之后那么也可以再次获取这个锁。
  • 锁超时:和本地锁一样支持锁超时,防止死锁。
  • 高效,高可用:加锁和解锁需要高效,同时也需要保证高可用防止分布式锁失效,可以增加降级。
  • 支持阻塞和非阻塞:和 ReentrantLock 一样支持 lock 和 trylock 以及 tryLock(long timeOut)。
  • 支持公平锁和非公平锁(可选):公平锁的意思是按照请求加锁的顺序获得锁,非公平锁就相反是无序的。这个一般来说实现的比较少。

3、一些比较常见的分布式锁方案

  • SETNX + EXPIRE
  • SETNX + value值是(系统时间+过期时间)
  • SET EX PX NX + 校验唯一随机值,再释放锁
  • 多机实现的分布式锁Redlock
  • ZooKeeper实现分布式锁
  • 使用数据库实现分布式锁

1)、方案一: SETNX和EXPIRE

伪代码如下:

if (setnx(key, 1) == 1){expire(key, 10)try {//TODO 业务逻辑} finally {del(key)}
}

这种方案的优点是优点是实现简单,通过修改过期时间可以支持锁重入,锁超时自动释放;

缺点:因为上述命令是分两步执行,如果第二步执行失败,将造成无法解锁, 很容易导致死锁。

2)、方案二: SETNX + value值是(系统时间+过期时间)

当前时间:  '2022-04-17 11:00:00'.to_time
value = '2022-04-17 11:00:10'.to_time // 10s后过期
if (setnx(key, value) == 1){ // 代码1try {//TODO 业务逻辑} finally {del(key)}
}else{if  redisClient.get(key_resource_id)  < Time.now { // 表示已过期del(key)goto 代码1 }
}

优点:加锁是原子操作,解决了方案一的缺点,避免了死锁问题。
缺点:实现复杂,每个机器的时间必须保持同步,其他加锁线程会修改过期时间,锁有可能被其他线程错误释放。

3)、SET EX PX NX + 校验唯一随机值,再释放锁

SETNX和EXPIRE 为两个指令, 不是原子性操作,如果 SETNX 成功,在设置锁超时时间后,服务器挂掉、重启或网络问题等,导致 EXPIRE 命令没有执行,锁没有设置超时时间变成死锁。针对该问题,redis 在2.6.12版本过后增加新的解决方案。

set key value [expiration EX seconds|PX milliseconds] [NX|XX]

EX seconds:将键的过期时间设置为 seconds 秒。
SET key value EX seconds 等同于 SETEX key seconds value
PX millisecounds:将键的过期时间设置为 milliseconds 毫秒。
SET key value PX milliseconds 等同于 PSETEX key milliseconds value
NX:只在键不存在的时候,才对键进行设置操作。
SET key value NX 等同于 SETNX key value
XX:只在键已经存在的时候,才对键进行设置操作

比如当key不存在时, 设置10s的锁, 可以这么设置:

SET product:10001 true  ex  10  nx

如果SET操作成功后,返回的是OK,失败返回NIL

最后为删除时,防止可能被其他线程误删。可以加锁时设置一下当前线程的一个随机ID, 然后在删除时判断一下。 伪代码如下:

if(redisClient.set(key_resource_id, uni_request_id, "NX", "EX", 100s) == 1){ //加锁try {... //业务处理}finally {//判断是不是当前线程加的锁,是才释放if (redisClient.get(key_resource_id) == uni_request_id) {redisClient.del(lockKey); //释放锁}}
}

这种方案的优点是可以保证加锁的原子性,使用LUA释放锁的话,锁不会被其他线程错误释放。

缺点:锁没有自动续期机制,锁无法支持重入。不过其实平时开发中, 大部分场景不用考虑自动续期机制。

4)、多机实现的分布式锁Redlock

Redis 官方站提出了一种权威的基于 Redis 实现分布式锁的方式名叫Redlock,此种方式比原先的单节点的方法更安全。

Redlock 的方案基于 2 个前提:

  • 不再需要部署从库和哨兵实例,只部署主库
  • 但主库要部署多个,官方推荐至少 5 个实例

整体的流程是这样的,一共分为 5 步:

a)、客户端先获取「当前时间戳T1」
b)、客户端依次向这 5 个 Redis 实例发起加锁请求(用前面讲到的 SET 命令),且每个请求会设置超时时间(毫秒级,要远小于锁的有效时间),如果某一个实例加锁失败(包括网络超时、锁被其它人持有等各种异常情况),就立即向下一个 Redis 实例申请加锁
c)、如果客户端从 >=3 个(大多数)以上 Redis 实例加锁成功,则再次获取「当前时间戳T2」,如果 T2 - T1 < 锁的过期时间,此时,认为客户端加锁成功,否则认为加锁失败
d)、加锁成功,去操作共享资源(例如修改 MySQL 某一行,或发起一个 API 请求)
e)、加锁失败,向「全部节点」发起释放锁请求(前面讲到的 Lua 脚本释放锁)

Redlock加锁步骤相对还是比较繁琐的,有点重,官方给出的解释是为了「容错」,部分实例异常宕机,剩余的实例加锁成功,整个锁服务依旧可用。

其实Redlock一出来, 就受到了业界著名的分布式系统专家Martin的质疑,他马上写了篇文章,质疑这个 Redlock 的算法模型是有问题的,并对分布式锁的设计,提出了自己的看法,之后,Redis 作者 Antirez 面对质疑,不甘示弱,也写了一篇文章,反驳了对方的观点,并详细剖析了 Redlock 算法模型的更多设计细节。这里就不展开细讲了, 感兴趣的朋友可以看看这个文章。(opens new window)

5)、也可以使用ZooKeeper实现分布式锁

Zookeeper的节点Znode有四种类型:

  • 持久节点:默认的节点类型。创建节点的客户端与zookeeper断开连接后,该节点依旧存在。
  • 持久节点顺序节点:所谓顺序节点,就是在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号,持久节点顺序节点就是有顺序的持久节点。
  • 临时节点:和持久节点相反,当创建节点的客户端与zookeeper断开连接后,临时节点会被删除。
  • 临时顺序节点:有顺序的临时节点。

Zookeeper分布式锁实现应用了临时顺序节点, 这里大概讲下zk分布式锁的实现原理吧。

大致思想为:每个客户端对某个方法加锁时,在ZooKeeper上与该方法对应的指定节点的目录下,生成一个唯一的临时有序节点。 判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。 当释放锁的时候,只需将这个临时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。

优点:

  • 有效的解决单点问题,不可重入问题,非阻塞问题以及锁无法释放的问题
  • 实现较为简单

缺点:

  • 性能上不如使用缓存实现的分布式锁,因为每次在创建锁和释放锁的过程中,都要动态创建、销毁临时节点来实现锁功能
  • 需要对ZooKeeper的原理有所了解

这里就不展开细讲ZooKeeper的原理, 后面会专门用一篇文章讲如何用Zookeeper实现分布式锁。

6)、使用数据库实现分布式锁

可以使用select ... for update 来实现分布式锁。我们自己的项目,分布式定时任务,就使用类似的实现方案

优点:

  • 简单,使用方便,不需要引入Redis、zookeeper等中间件。

缺点:

  • 不适合高并发的场景
  • db操作性能较差,有锁表的风险;

结语:

  • 从性能角度(从高到低)Redis > Zookeeper >= 数据库;
  • 从理解的难易程度角度(从低到高)数据库 > Redis > Zookeeper;
  • 从实现的复杂性角度(从低到高)Zookeeper > Redis > 数据库;
  • 从可靠性角度(从高到低)Zookeeper > Redis > 数据库。
  • 平时开发中 SET EX PX NX + 校验唯一随机值,再释放锁 方案就可以了。

这些知识点的导图和问题的答案详解的PDF文档都可以免费分享给大家

2022年Redis最新面试题- Redis分布式锁相关推荐

  1. 2022年Redis最新面试题- Redis集群

    最近整理一份关于Redis常见面试题的,也会根据自己的经验, 标注一些出现的概率,最高5颗★出现的概率最高.比如这样: Redis 最适合的场景, 可以简单的说说吗? 出现概率: ★★★★ 整体目录大 ...

  2. 2022年Redis最新面试题 - Redis缓存问题

    缓存问题 分布式缓存 Redis缓存雪崩 Redis缓存击穿 Redis缓存穿透 缓存预热 缓存降级 #Redis缓存雪崩 出现概率: ★★★★★ 这个在Redis面试的题目中算是出镜率特别高的问题了 ...

  3. 2022年Redis最新面试题

    2022年Redis最新面试题 一.Redis基础知识 1.什么是 Redis, 有哪些优缺点? 2.Redis 最适合的场景, 可以简单的说说吗? 3.Redis 相比 Memcached 有哪些优 ...

  4. 2022年MySQL最新面试题

    2022年MySQL最新面试题目录 前言 一.数据库基础知识 0.概要 1.平时MySQL主要用哪个版本 2.数据库三大范式是什么 3.MySQL有关权限的表都有哪几个 4.MySQL的binlog有 ...

  5. redis实现轮询算法_【07期】Redis中是如何实现分布式锁的?

    点击上方"Java面试题精选",关注公众号 面试刷图,查缺补漏 分布式锁常见的三种实现方式: 数据库乐观锁: 基于Redis的分布式锁: 基于ZooKeeper的分布式锁. 本地面 ...

  6. 2022年Redis最新面试题第3篇 - Redis事务

    事务 怎么理解 Redis 事务? Redis事务执行过程 Redis事务的一些使用场景 Redis事务与Redis pipeline的区别 集群模式下Redis事务如何保证原子性 怎么理解 Redi ...

  7. 【面试题】Redis中是如何实现分布式锁的

    分布式锁常见的三种实现方式: 数据库乐观锁: 基于Redis的分布式锁: 基于ZooKeeper的分布式锁. Redis的分布式锁 Redis要实现分布式锁,以下条件应该得到满足 互斥性:在任意时刻, ...

  8. 为什么redis取出来是null_[2020] Redis 最新面试题

    Redis 的数据类型(数据结构) string (二进制安全,可以存储任意类型的数据) list(链表) 字典(就是hashmap) set(不重复无序的hashmap) zset(按照给定的 sc ...

  9. Redis 实现优惠券秒杀、分布式锁、消费队列

    文章目录 一.全局唯一ID 1.1 为啥需要全局唯一ID 1.2 全局ID生成器 1.3 全局唯一ID生成策略 二.实现优惠卷秒杀下单 2.1 优惠卷表结构 2.2 秒杀功能实现 三.超卖问题 四.实 ...

最新文章

  1. Spark之SQL解析(源码阅读十)
  2. 把二元查找树转变成排序的双向链表
  3. JavaScript触摸与手势事件
  4. 自定义注解做数据验证
  5. eclipse打包成jar_Spring Boot 打包成的可执行 jar ,为什么不能被其他项目依赖?
  6. 求数组中的最长递增子序列
  7. 图灵社区 和 大家网
  8. uni-app运行编译报错
  9. jvm垃圾回收机制_JVM的垃圾回收机制总结
  10. 增加window服务器,Windows Server2012入门-添加服务器角色和功能
  11. 硬件电子c语言笔试,电子类常见笔试试题
  12. ajax js java省市三级联动菜单,javaweb--json--ajax--mysql实现省市区三级联动(附三级联动数据库)(示例代码)...
  13. openlayers2渐变色渲染
  14. 单目结构光三维扫描仪的标定与三维重建
  15. 2020 年 Github 上最牛的 Java 进阶教程及 Java 实战项目都在这里了!
  16. NMOS、PMOS、PNP、NPN三极管 做开关使用时的电路设计
  17. Convert Nero's nrg file to iso file
  18. 为什么文本框里的字只显示一半_Word文本框文字显示不全、无法选择、不能编辑调整大小和跨页,怎么解决...
  19. 一个视频分割为多个视频片段
  20. 团队作业第二次——需求分析

热门文章

  1. java基于ssm的高校学生学籍信息管理系统
  2. python基础语法大全turtle_Python 基础语法-turtle篇-Go语言中文社区
  3. 《花开半夏》--3 对峙(2)
  4. Java应用_获取购物小票数字信息
  5. 计算机氧气游戏,外媒分享空间模拟新作《氧气不足》游戏体验
  6. 微软面试题:利用天平砝码,三次将140克的盐 分成50、90克两份?
  7. 第一行输出一个1,第二行输出2个2······第N行输出N个N
  8. 街篮 服务器 位置,贺岁杯丨16强集结 精彩直播一触即发
  9. vc++ 线程和线程锁 (一)
  10. 安装Vue的脚手架时遇到的无法安装问题