《对线面试官》| 高频 Redis 面试题 pt.1

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 《对线面试官》| 高频 Redis 面试题

1、谈下你对 Redis 的了解

Redis 是一个用 C 语言编写的、开源的 key-value 数据库

Redis 运行在内存中,所以处理数据的速度非常快,同时 Redis 还支持数据的持久化,将内存中的数据保存在磁盘

2、Redis适用于哪些场景?不适用于哪些场景?

适用的场景:

  1. 会话缓存:减轻后端sql数据库的IO压力,提升系统性能
  2. 排行榜:利用 sortset(有序集合)可以排序且不能有重复数据的特性来实现
  3. 消息队列:redis 支持生产者/消费者模式、发布者/订阅者模式的消息队列

不适用场景:

  1. 数据量太大的业务场景:内存成本大
  2. 数据访问频率非常低的业务场景:浪费内存资源

3、Redis 支持的数据类型有哪些?

  1. string(字符串)

字符串类型是redis最基础的数据结构,而且其他集中数据结构都是在字符串类型基础上构建的

  1. Hash(哈希)

Redis中哈希类型是指键本身是一种键值对结构

  1. List(列表)

列表(list)类型是用来存储多个有序的字符串,是一种线性结构可以充当栈和队列的角色

  1. Set(集合)

集合(set)类型也是用来保存多个的字符串元素,集合中不允许有重复出现的元素

集合的元素是无序的,不能够通过下标来获得值

  1. zset(即sotred set:有序集合)

有序集合保留了集合不能有重复成员的特性,不同的是有序集合中的元素是可以排序的。

和列表使用索引下标作为排序依据不同的是它给每个元素设置一个分数(score)作为排序的依据

4、Redis是单线程架构,但为什么这么快?

  • Redis 的数据都是存放在内存上,绝大部分请求都是对内存进行操作,非常快速
  • 非阻塞I/O,Redis使用 epoll 作为I/O多路复用技术的实现;加上Redis自身事件处理模型将epoll中的连接,读写,关闭都转换为事件,不会在网络I/O上浪费过多时间
  • 单线程避免了不必要的因上下文切换、多线程资源竞争所导致的资源消耗,更加快速

5、什么是缓存穿透?怎么解决?

  • 缓存穿透

是指当查询一个不存在的数据时,由于缓存不命中就会去数据库查询

如果每次都去查询一个不存在的数据,就会导致这个不存在的数据每次请求都要到数据库中查询,造成缓存穿透

  • 解决方法

将空数据缓存,如果查询一个数据返回空值(不管数据存不存在还是系统故障),仍把这个空结果缓存起来,并设置过期时间

布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一定不存在的数据会被这个 bitmap 拦截掉,从而避免对数据库的查询压力

6、什么是缓存雪崩?该如何解决?

  • 缓存雪崩

指的是缓存集中在一段时间内失效,发生了大量的缓存穿透,导致所有的查询操作都落在数据库上,造成了缓存雪崩

  • 解决方法

加锁排队:缓存失效后,通过加锁或者队列来控制对数据库进行操作的线程数量,避免数据库压力过大

数据预热:通过缓存 reload 机制,预先更新缓存,在即将发生大并发访问前手动触发缓存,并设置不同的过期时间

二级缓存(双缓存)策略:Cache1 为原始缓存,Cache2 为拷贝缓存,Cache1 失效时,可以访问 Cache2,Cache1 缓存失效时间设置为短期,Cache2 设置为长期

在缓存的时候给过期时间加上一个随机值,这样就会大幅度的减少缓存在同一时间过期

7、Redis 持久化机制有哪几种

Redis是将数据运行在内存中的,如果出现服务挂掉或者服务器宕机都可以导致数据全部丢失,为了解决这个问题 redis 提供了两种数据持久化机制——RDB、AOF

  • RDB

RDB 是 Redis DataBase 的缩写

按照一定时间间隔把内存中的数据以快照的形式(dump.rdb)保存到磁盘中

触发RDB持久化过程为手动触发和自动触发

手动触发:save 命令或 bgsave 命令

自动触发:配置文件添加 save 字段

  • AOF

AOF 是 Append-only file 的缩写

Redis 会将每一个收到的写命令都追加到 AOF 文件最后,类似于 MySQL 的 binlog,Reids重启后会通过重新执行 AOF 文件中的写命令来实现数据的恢复

通过在配置文件里添加 appendonly yes 字段来开启 AOF

  • 两者区别

RDB 使用快照的形式来持久化整个 Redis 数据,而 AOF 只是将每次执行的命令追加到 AOF
文件

如果两个都配置了,优先采用 AOF

AOF 提供了多种数据同步频率,最多丢失 1 秒的数据而已,RDB是隔一段时间进行持久化,比 RDB 安全

对于具有相同数据的的 Redis,AOF 文件通常会比 RDB 文件体积更大

8、在进行RDB持久化时,Redis 可以处理写请求吗

可以,Redis 使用操作系统的多进程写时复制技术 COW(Copy On Write) 来实现快照持久化,保证数据一致性

Redis 在 RDB 持久化时会 fork 出一个子进程,由子进程来负责持久化,而父进程继续处理客户端请求

当父进程收到客户端的写请求时,就会将数据复制一份传给子进程,子进程将副本数据写到 RDB 文件里

9、谈谈 Redis 的内存回收机制吧

Redis是基于内存的数据库,常被用作缓存,以此来提高系统的响应速率与性能

因此在一些业务场景中往往会出现 Redis 消耗了大量的内存,导致系统出现性能瓶颈,为此 Redis 提供了内存回收机制(Redis默认采用noeviction策略)
image-20220919153309057.png

volatile-lru:
#在设置了过期时间的所有键中,选取最近最少使用的数据删除。

volatile-lfu:
#在设置了过期时间的所有键中,选取最近最不常用,也就是一定时期内被访问次数最少的数据删除

volatile-random:
#筛选出设置了过期时间的键值对,随机删除。

volatile-ttl:
#筛选出设置了过期时间的键值对,越早过期的越先被删除。

allkeys-lru:
#在所有键中,选取最近最少使用的数据删除

allkeys-lfu:
#在所有键中,选取最近最不常用,也就是一定时期内被访问次数最少的数据删除

allkeys-random:
#采用随机淘汰策略删除所有的键值对,这个策略不常用。

noeviction:
#不淘汰任何键值对,当内存满时,如果进行读操作,例如get命令,它将正常工作,而做写操作,它将返回错误,也就是说,当Redis采用这个策略内存达到最大的时候,它就只能读不能写了

10、谈谈 Redis 的键过期机制吧

除了 Redis 的内存回收机制可以有效解决消耗内存过高的问题

还有一个键过期机制,通过给 key 设置一个过期时间,超过过期时间后 key 就会被删除,内存就被回收

Redis key过期处理的方式有三种

  • 惰性删除

    不管键有没有过期都不主动删除,等到每次去获取键时再判断是否过期,如果过期就删除该键,否则返回键对应的值。这种策略对内存不够友好,可能会浪费很多内存

    缺点:若大量的key在超出超时时间后,很久一段时间内,都没有被获取过,那么可能发生内存泄露(无用的数据占用了大量的内存)

  • 定时删除

    在设置key的过期时间的同时,还会为该key创建一个定时器,让定时器在key的过期时间来临时,对key进行删除

    缺点:定时器的创建耗时,若为每一个设置过期时间的key创建一个定时器(将会有大量的定时器产生),性能影响严重,因为每个定时器都会占用一定的 CPU 资源

  • 定期删除

    系统每隔一段时间就定期扫描一次,发现过期的键就进行删除

    以下两种方式可以触发定期删除

    • 配置redis.conf 的hz选项,默认为10 (即1秒执行10次,100ms一次,值越大说明刷新频率越快,最Redis性能损耗也越大)
    • 配置内存回收策略,当Redis消耗内存达到最大内存使用限制,就会自行对应的策略,来对过期key进行删除

Redis 当中,其选择的是策略 2 和策略 3 的综合使用。不过 Redis 的定期删除只会扫描设置了过期时间的键,因为设置了过期时间的键 Redis 会单独存储,所以不会出现扫描所有键的情况

11、同一时间大量 key 都过期的话会有什么影响?

  • 读写请求响应时间变长

当 key 过期后,内存管理器需要对 key 占用的内存进行回收,会产生一定的 CPU 消耗

大量的 key 过期会导致频繁回收内存,消耗 CPU 资源,导致系统响应变慢

  • 缓存雪崩

缓存失效后导致所有的查询操作都落在数据库上,造成了缓存雪崩

12、slave是怎么实现键过期策略的?

slave 不会进行过期扫描, slave 对过期 key 的处理是被动的

当 master 采用定期或惰性删除过期 key 时,会同步一个 del 操作到 slave,这样 slave 也可以删除过期 key

RDB对过期Key的处理

  • 持久化数据到RDB文件

    • 持久化之前会检查 key 是否过期,过期的 key 不进入RDB文件
  • 从RDB文件恢复数据

    • 数据载入数据库之前,会对 key 进行过期检查,如果过期则不导入数据库(主库)
    • 如果 RDB 文件里有过期的键,那还是会载入,但是主从在数据同步时(全量复制),slave的数据会被清空(丢弃原先所有数据),所以不影响

AOF对过期Key的处理

  • 持久化数据到 AOF 文件

    • 如果某个 key 过期,还没有被删除,该 key 是不会进入 aof 文件的,因为没有发生修改命令
    • 当 key 过期被删除后,就会向 aof 文件追加一条 del 命令(在将来的以 aof 文件恢复数据的时候该过期的键就会被删掉)
  • AOF重写

    • 重写时,会先判断 key 是否过期,已过期的 key不会重写到 aof 文 件
相关实践学习
基于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
相关文章
|
1月前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
29天前
|
存储 NoSQL 算法
阿里面试:亿级 redis 排行榜,如何设计?
本文由40岁老架构师尼恩撰写,针对近期读者在一线互联网企业面试中遇到的高频面试题进行系统化梳理,如使用ZSET排序统计、亿级用户排行榜设计等。文章详细介绍了Redis的四大统计(基数统计、二值统计、排序统计、聚合统计)原理和应用场景,重点讲解了Redis有序集合(Sorted Set)的使用方法和命令,以及如何设计社交点赞系统和游戏玩家排行榜。此外,还探讨了超高并发下Redis热key分治原理、亿级用户排行榜的范围分片设计、Redis Cluster集群持久化方式等内容。文章最后提供了大量面试真题和解决方案,帮助读者提升技术实力,顺利通过面试。
|
1月前
|
存储 NoSQL 算法
面试官:Redis 大 key 多 key,你要怎么拆分?
本文介绍了在Redis中处理大key和多key的几种策略,包括将大value拆分成多个key-value对、对包含大量元素的数据结构进行分桶处理、通过Hash结构减少key数量,以及如何合理拆分大Bitmap或布隆过滤器以提高效率和减少内存占用。这些方法有助于优化Redis性能,特别是在数据量庞大的场景下。
面试官:Redis 大 key 多 key,你要怎么拆分?
|
2月前
|
NoSQL Java API
美团面试:Redis锁如何续期?Redis锁超时,任务没完怎么办?
在40岁老架构师尼恩的读者交流群中,近期有小伙伴在面试一线互联网企业时遇到了关于Redis分布式锁过期及自动续期的问题。尼恩对此进行了系统化的梳理,介绍了两种核心解决方案:一是通过增加版本号实现乐观锁,二是利用watch dog自动续期机制。后者通过后台线程定期检查锁的状态并在必要时延长锁的过期时间,确保锁不会因超时而意外释放。尼恩还分享了详细的代码实现和原理分析,帮助读者深入理解并掌握这些技术点,以便在面试中自信应对相关问题。更多技术细节和面试准备资料可在尼恩的技术文章和《尼恩Java面试宝典》中获取。
美团面试:Redis锁如何续期?Redis锁超时,任务没完怎么办?
|
2月前
|
NoSQL 算法 Redis
Redis面试篇
Redis面试篇
58 5
|
1月前
|
存储 NoSQL Redis
Redis常见面试题:ZSet底层数据结构,SDS、压缩列表ZipList、跳表SkipList
String类型底层数据结构,List类型全面解析,ZSet底层数据结构;简单动态字符串SDS、压缩列表ZipList、哈希表、跳表SkipList、整数数组IntSet
|
2月前
|
缓存 NoSQL 算法
面试题:Redis如何实现分布式锁!
面试题:Redis如何实现分布式锁!
|
4月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
1月前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
1月前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
下一篇
DataWorks