聊聊Redis面试题

本文涉及的产品
云数据库 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
相关文章
|
2月前
|
NoSQL Redis Sentinel
【怒怼大厂面试官】听说你精通Redis?说说Redis哨兵
面试官:Redis哨兵知道吧?知道的,Sentinel哨兵本质是一个运行在特殊模式下的Redis服务器。面试官:嗯然后呢?它的主要作用是通过检测Redis主从服务器的下线状态,选举出新Redis主服务器,也就是故障转移,来保证Redis的高可用性。
79 4
【怒怼大厂面试官】听说你精通Redis?说说Redis哨兵
|
23天前
|
NoSQL MongoDB Redis
Python与NoSQL数据库(MongoDB、Redis等)面试问答
【4月更文挑战第16天】本文探讨了Python与NoSQL数据库(如MongoDB、Redis)在面试中的常见问题,包括连接与操作数据库、错误处理、高级特性和缓存策略。重点介绍了使用`pymongo`和`redis`库进行CRUD操作、异常捕获以及数据一致性管理。通过理解这些问题、易错点及避免策略,并结合代码示例,开发者能在面试中展现其技术实力和实践经验。
312 8
Python与NoSQL数据库(MongoDB、Redis等)面试问答
|
1月前
|
缓存 NoSQL Java
面试官:Redis如何实现延迟任务?
延迟任务是计划任务,用于在未来特定时间执行。常见应用场景包括定时通知、异步处理、缓存管理、计划任务、订单处理、重试机制、提醒和数据采集。Redis虽无内置延迟任务功能,但可通过过期键通知、ZSet或Redisson实现。然而,这种方法精度有限,稳定性较差,适合轻量级需求。Redisson的RDelayedQueue提供更简单的延迟队列实现。
364 9
|
1月前
|
缓存 NoSQL 定位技术
深入探索Redis:面试中必须掌握的关键知识点
深入探索Redis:面试中必须掌握的关键知识点
|
1月前
|
NoSQL Java 测试技术
面试官:如何搭建Redis集群?
**Redis Cluster** 是从 Redis 3.0 开始引入的集群解决方案,它分散数据以减少对单个主节点的依赖,提升读写性能。16384 个槽位分配给节点,客户端通过槽位信息直接路由请求。集群是无代理、去中心化的,多数命令直接由节点处理,保持高性能。通过 `create-cluster` 工具快速搭建集群,但适用于测试环境。在生产环境,需手动配置文件,启动节点,然后使用 `redis-cli --cluster create` 分配槽位和从节点。集群动态添加删除节点、数据重新分片及故障转移涉及复杂操作,包括主从切换和槽位迁移。
35 0
面试官:如何搭建Redis集群?
|
2月前
|
运维 负载均衡 NoSQL
【大厂面试官】知道Redis集群和Redis主从有什么区别吗
集群节点之间的故障检测和Redis主从中的哨兵检测很类似,都是通过PING消息来检测的。。。面试官抓抓脑袋,继续看你的简历…得想想考点你不懂的😰。
69 1
|
2月前
|
NoSQL Redis
【怒怼大厂面试官】听说你精通Redis?Redis数据同步懂吗
面试官:不用慌尽管说,错了也没关系。。。来说说Redis数据同步。是这样的,Redis有一个叫命令传播的概念,如果像面试官说的这种场景,再使用上面我提到的AOF缓冲区就有点浪费内存空间了。所以Redis会将主服务器的这条Del删除命令
63 2
【怒怼大厂面试官】听说你精通Redis?Redis数据同步懂吗
|
2月前
|
NoSQL Redis 数据库
【怒怼大厂面试官】听说你精通Redis?说说Redis持久化
咳咳咳,看你简历写了精通Redis,那我就随便问问。主要有RDB持久化、AOF持久化。是这样,Redis服务器会维护一个AOF重写缓冲区,该缓冲区会在子进程创建新AOF文件期间,记录服务器执行的所有写命令。
56 1
【怒怼大厂面试官】听说你精通Redis?说说Redis持久化
|
3月前
|
缓存 NoSQL Linux
面试必备:一线大厂Redis设计规范与性能优化
本文梳理了在使用Redis过程需要遵循的一些最佳实践,包括针对架构维度的一些深入性能优化的知识,如果面试官问你:"说下在使用Redis的过程中,需要注意哪些规范?",如果你按照本文的思路回答,肯定能让面试官眼前一亮,offer自然就到手了。
57 0
面试必备:一线大厂Redis设计规范与性能优化
|
3月前
|
存储 NoSQL Java
面试官:Redis如何保证高可用?
面试官:Redis如何保证高可用?
82 2
面试官:Redis如何保证高可用?