聊聊Redis面试题

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 大家好,许久不见,我是Leo。最近抽了一部分时间在BOOS上解答了一些面试题,点赞量和Get 数挺多的。这篇文章就聊一些Redis的一些面试题。

什么是Redis的缓存预热?


缓存预热主要是双十一流量比较大的业务场景。为了提升用户的访问性能,减少一开始缺少缓存Key到数据库查询数据的慢性能问题。一般会采用系统上线前把热点缓存预热到redis中。这样用户就不用一开始去数据库查了,直接Redis内存返给你了。


Redis单线程性能为什么优于多线程?


一个CPU在运行多个线程时,会存在多线程调用的消耗问题,而且还有多个线程调用时数据一致性的问题。这些都要单独处理,单独处理又会消耗性能。于是Redis统筹兼顾采用了单,多线程并用的思路。

在处理数据写入,读取属于键值对数据操作,采用单线程操作。在请求连接,从socket中读取请求,解析客户端发送请求,采用多线程操作

Redis巧妙的把所有需要延迟等待的操作全部转交给了多线程处理,在不需要等待的全部单线程处理。个人感觉这种设计思路很棒


多路复用机制

IO多路复用机制是指一个线程处理多个IO流,也是我们经常听到的select/epoll机制。那么那些连接,等待的操作Redis都是如何处理的呢?

在Redis只运行单线程的情况下,同一时间存在多个监听套接字,和已连接的套接字,内核会一直监听这些连接请求和数据请求。一旦客户端发送请求就会以事件的方式通知Redis主线程处理。这就是Redis线程处理多个IO流的效果。

上文说到以事件方式通知Redis这里我们做一个扩展,select/epoll提供了基于事件的回调机制,不同的事件会调用相应的处理函数。一旦请求来了,立刻加到事件队列中,Redis单线程就会源源不断的处理该事件队列。解决了等待与扫描的资源浪费问题。


Redis中如何解决缓存的一致性问题

很多人一上来就是加锁,这样的回答显然不是面试官想看到的,我们可以搭一个知识树。比如可以这样回答。

Redis缓存分为两种 读写缓存只读缓存 。不同的缓存类型会引发不同的问题。

对于读写缓存来说,读压力和写压力都来源于一个库,如果对数据发生了修改。我们除了要考虑数据库的一致性以外,还要考虑缓存中的数据一致性。

这里可以展开聊一下写压力的写回策略

  • 当采用同步直写策略,写缓存时,可以保证缓存与数据库的数据一致性。
  • 当采用异步写回策略,写缓存时,由于是异步执行,无法保证命令都执行也就是无法保证数据一致性。

上述策略如何选择主要看业务的需求了,如果核心数据,一定不能错的数据,我们可以同步直写再搭配事务机制。如果不是特别重要的数据,那我们就可以采用异步写回策略来提升性能。

对于只读缓存来说,会有一个子库,专门提供读服务,但是如果有新数据进来,子库必须跟着主库进行数据同步,来保证主从库的数据一致性。

这里可以展开聊一下 Redis,MySQL的原子性是怎么保证的

  • 如果先删缓存,后更新数据库:缓存删除成功,数据更新失败,导致用户向缓存读数据时,没有发现缓存key就会打向数据库,而数据库数据没有更新成功导致读到旧值
  • 如果先更新数据库,后删缓存: 更新数据库成功时,缓存删除失败,就会导致数据库保留了最新的值,用户向Redis读数据时,发现缓存key存在,直接返回了就拿到了上一个旧值。

会发现上述都不能保证,这里为什么我还要提呢?告诉面试官你是经过很多思考的,别搞的跟背答案似的。

解决方案

可以采用重试机制,比如用Redis的List当做消息队列,或者采用MQ消息队列来处理。

不管是 先删缓存,后更新数据库 还是 先更新数据库后删缓存 一旦失败就会出现两边不一致的情况,那我们就可以采用MQ消费机制,只有当两种情况全部成功,才把MQ这条数据删掉,要不然就重复消费。也就是重新再执行一遍。

这里扩展一下,我们在执行重复消费的那一刻,如果有数据打过来怎么办?

所以我们在解决时,一般会给他sleep一小段时间再进行缓存操作。这样就会避免这种那一刻的误差。


Redis为什么要设置随机过期时间


Redis设置的过期时间问题,如果很多key在同一时刻大面积过期,会影响Redis的性能。

Redis是使用单线程读写数据的,大面积过期会阻塞Redis的处理效率。所以,在应用Redis的key时要避免两种情况,bigkey大面积过期key

对于第二种情况,我们只要设置一个随机过期时间就不会存在大面积过期啦。

这里还可以跟面试官聊一下Redis的过期删除策略和过期的删除机制。因为上文的删除key的依据是来源于过期策略和删除机制的。


过期删除机制

过期删除机制是Redis用来回收内存空间的常用机制,可以对键值对设置过期时间,默认情况下,Redis每100毫秒就会删除一些过期的key,具体算法如下:

  • 采样 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 个数的 key,并将其中过期的 key 全部删除;
  • 如果超过 25% 的 key 过期了,则重复删除的过程,直到过期 key 的比例降至 25% 以下。

ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 默认为20。毫秒的概念可能不太明显,我们换算一下也就是每秒删除200个过期key(20个/100毫秒)=(200个/秒)

如果按照第一种的话,并不是造成太大的影响。如果命中了第二种,就会造成key大面积失效过期,过期的key超过了25%,会一直删除直至降至25%。这段删除期间会大量释放内存空间,大量插入链表填补。Redis就变慢了。


过期删除策略

这个应该是比较简单的

  • 定时删除:采用定时器方式,时间一到就删
  • 惰性删除:惰性删除并不是当到达过期时间去删除,而是每次获取键值时,会判断是否过期,如果过期就删,并返回空。没过期就返回键值
  • 定期删除:每隔一段时间,就对数据库中的键进行检查,如果过期则删除。至于要删除多少什么时候删除则是通过具体程序绝对的

定时删除策略

优点是:对内存友好。因为通过定时器,当一个键到达过期时间时就会立马被删除,直接就释放了内存。

缺点是:对 CPU 不友好。因为如果过期键比较多,那么删除这些过期键会占用相当一部分 CPU 时间,如果 CPU 时间非常紧张的话,还将 CPU 时间用在删除和当前任务无关的过期键上,会对服务器的响应时间以及吞吐量造成影响。

因此,通过 定时删除 策略来时间过期键的删除不太现实。

惰性删除

优点:对 CPU 时间友好。程序只会在取出键时才会判断是否删除,并且只作用到当前键上,其他过期键不会花费 CPU 时间去处理。

缺点:对内存不友好。因为只有键被使用时才会去检查是否删除,如果有大量的键一直不被使用,那么这些键就算过期了也不会被删除,会一直占用着内存。这种可以理解为是一种内存泄漏——大量无用的数据一直占用着内存,并且不会被删除。

定期删除

相比较定时删除对 CPU 的不友好,惰性删除的对内存不友好。定期删除采用了一种折中的方式:

定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对 CPU 时间的影响。并且,通过定期删除过期键,有效的减少了过期键带来的内存浪费。但删除的时长和频率比较难定义,

因为:如果频率太高或者时长太长,那么会占用大量的 CPU 时长。如果过短又会出现内存浪费的情况。

因此。如果采用定期删除策略的话需要通过具体的业务场景来定义时长和频率。


相关实践学习
基于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
相关文章
|
18天前
|
存储 NoSQL Java
可能是最漂亮的Redis面试基础详解
我是南哥,相信对你通关面试、拿下Offer有所帮助。敲黑板:本文总结了Redis基础最常见的面试题!包含了Redis五大基本数据类型、Redis内存回收策略、Redis持久化等。相信大部分Redis初学者都会忽略掉一个重要的知识点,Redis其实是单线程模型。我们按直觉来看应该是多线程比单线程更快、处理能力更强才对,比如单线程一次只可以做一件事情,而多线程却可以同时做十件事情。但Redis却可以做到每秒万级别的处理能力,主要是基于以下原因:(1)Redis是基于内存操作的,Redis所有的数据库状态都保存在
可能是最漂亮的Redis面试基础详解
|
6天前
|
NoSQL Java API
美团面试:Redis锁如何续期?Redis锁超时,任务没完怎么办?
在40岁老架构师尼恩的读者交流群中,近期有小伙伴在面试一线互联网企业时遇到了关于Redis分布式锁过期及自动续期的问题。尼恩对此进行了系统化的梳理,介绍了两种核心解决方案:一是通过增加版本号实现乐观锁,二是利用watch dog自动续期机制。后者通过后台线程定期检查锁的状态并在必要时延长锁的过期时间,确保锁不会因超时而意外释放。尼恩还分享了详细的代码实现和原理分析,帮助读者深入理解并掌握这些技术点,以便在面试中自信应对相关问题。更多技术细节和面试准备资料可在尼恩的技术文章和《尼恩Java面试宝典》中获取。
美团面试:Redis锁如何续期?Redis锁超时,任务没完怎么办?
|
12天前
|
NoSQL 算法 Redis
Redis面试篇
Redis面试篇
31 5
|
13天前
|
缓存 NoSQL Java
Java中redis面试题
Java中redis面试题
25 1
|
1月前
|
存储 缓存 NoSQL
【Java面试题汇总】Redis篇(2023版)
Redis的数据类型、zset底层实现、持久化策略、分布式锁、缓存穿透、击穿、雪崩的区别、双写一致性、主从同步机制、单线程架构、高可用、缓存淘汰策略、Redis事务是否满足ACID、如何排查Redis中的慢查询
【Java面试题汇总】Redis篇(2023版)
|
18天前
|
NoSQL Redis
redis 的 key 过期策略是怎么实现的(经典面试题)超级通俗易懂的解释!
本文解释了Redis实现key过期策略的方式,包括定期删除和惰性删除两种机制,并提到了Redis的内存淘汰策略作为补充,以确保过期的key能够被及时删除。
37 1
|
2天前
|
存储 缓存 NoSQL
面试官:Redis如何实现延迟任务?
面试官:Redis如何实现延迟任务?
11 0
|
1月前
|
缓存 监控 NoSQL
阿里面试让聊一聊Redis 的内存淘汰(驱逐)策略
大家好,我是 V 哥。粉丝小 A 面试阿里时被问到 Redis 的内存淘汰策略问题,特此整理了一份详细笔记供参考。Redis 的内存淘汰策略决定了在内存达到上限时如何移除数据。希望这份笔记对你有所帮助!欢迎关注“威哥爱编程”,一起学习与成长。
|
11天前
|
缓存 NoSQL 算法
面试题:Redis如何实现分布式锁!
面试题:Redis如何实现分布式锁!
|
2月前
|
缓存 NoSQL Redis
redis常见面试题总结(上)
Redis 提升读写性能,减少 MySQL 请求。优点包括:内存存储加速数据获取,支持多样数据结构如哈希和有序集合,事务确保操作原子性,具备队列、主从复制及持久化功能。相较于 Memcache,Redis 数据类型更丰富,支持数据持久化与恢复,单值大小可达 512MB。其单线程设计基于 C 语言实现,使用非阻塞 IO 复用来高效处理请求。主从同步机制确保数据一致性,首次同步需生成 RDB 文件。事务虽保证命令序列化执行但不支持回滚。Bigkey 会增加网络负载并可能导致内存不平衡。缓存雪崩、穿透等问题可通过分散过期时间和布隆过滤器解决。缓存预热则预先填充热点数据。
31 0