《面试心经》---Redis基础

一叶障目,不见Offer

前言

Redis 在当今后端技术的世界有着举足轻重的地位。几乎所有的后端技术面试官都会围绕 Redis 的原理和使用对面试者进行全方位、无死角的盘问。来自Redis的盘问或许会迟到,但它绝不会缺席。看着一个个自信的小眼神被面试官折磨的黯淡无光,老衲实属不忍。在一个月黑风高的夜晚,终于下定决心,收集整理Redis面试资料,著《面试心经》系列,望能普渡众生。

面试开始

一个穿着邋里邋遢的秃顶中年人抱着一个满是划痕的Mac向你走来。看你着那稀疏的头发,心想我艹,这至少也是个高级架构师了吧。但是看过《面试心经》的我们,依然可以气定神闲、稳如泰山

在这里插入图片描述

小伙子你好,看你简历上写了项目中有使用Redis,为什么要使用 Redis ?

这时的你心里忍不住暗骂,头都秃成这样了,问的问题如此平常,就这?但是你不能表现出来。

认真回答道:帅气又迷人的面试官你好。当时是因为项目使用的人越来越多,只使用传统的关系型数据库(如:MySQL)已不能满足项目的需求。出于对项目的性能并发方面考虑,需要在项目中引入缓存中间件。当时综合比较了常用的缓存中间件 Redis 和 Memcache 的优缺点之后,最终决定选择使用Redis

这里很可能会问你 Redis 和 Memcache 都有哪些区别,和他们各自的优缺点。感兴趣的少侠可以去查阅资料了解下,后续我也会出文章详细介绍对比

那你说说 Redis 都有哪些数据类型 ?

一气呵成的回答道:redis 支持多种类型的数据结构,常用的有5种 ,分别是 strings,hashes, lists, sets,sorted sets

这五种数据结构一定要做到倒背如流、一气呵成。知道每种数据结构的使用场景和底层实现原理更好

但是,如果你想要突出自己,还需要加上下面几种数据结构: bitmaps, hyperloglogs, geospatial indexes ,streams

回答到这里,基本就达到让面试官睁眼的水平了

小伙子,那你知道 Redis String 的底层实现方式吗 ?

这时你心想:我只是来面试个月薪 1K 的 CV 攻城狮啊,为什么要我经历这些。呸,真不要脸!但你依然不能表露出来,不能让面试官的奸计得逞

略做思考,答:字符串对象底层数据结构实现为 简单动态字符串(SDS)直接存储。(注:SDS是一个redis 定义的结构体)

这里只要能够说出 SDS,基本就可以了,如果还能够详细介绍 SDS 结构的内部构造更佳

Redis的持久化了解么?请简单介绍一下

风轻云淡道:Redis持久化有两种, RDBAOF

RDB做全量持久化(Redis默认的持久化方式)。按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二进制文件。对应产生的数据文件为dump.rdb,通过配置文件中的save参数来定义快照的周期。( 快照可以是其所表示的数据的一个副本,也可以是数据的一个复制品。)

AOF做增量持久化:Redis会将每一个收到的写命令都通过Write函数追加到文件最后,类似于MySQL的binlog。必要时,可以通过重新执行文件中保存的写命令来在内存中重建整个redis数据库。

Redis本身的机制是:当AOF持久化开启且存在AOF文件时,优先加载AOF文件。当AOF持久化关闭或不存在AOF文件时,加载RDB文件。加载AOF/RDB文件成功之后,Redis启动成功。如果AOF/RDB文件存在错误,则Redis启动失败并打印错误信息

了解 Pipeline 吗?请简单介绍一下

可以将多条命令一起打包发送至redis处理,处理完成后,将处理结果按照顺序打包,一起返回。好处是可以减少I/O次数,提升redis吞吐量。不过有两点需要注意:一个 pipeline 中的命令互相之间不能有因果关系。另外,一个 pipeline 中的命令不宜过多,不然数据量过大,增加客户端的等待时间,还可能造成网络阻塞。可以将大量命令的拆分多个小的pipeline命令完成。

那你使用过 Redis 分布式锁吗?怎么实现

先使用 setnx 争抢锁,抢到之后使用 expire 给锁加一个过期时间,防止忘记释放锁

那如果在执行 setnx 之后,执行 expire 之前进程意外 crash 或者要重启维护了,会怎么样?

故作惊讶的回答:如果这样的话,这个锁就永远得不到释放了!此时你可以作思考状(思考时间别太长,可能会让面试官误以为你不知道怎么处理,建议3s 左右为宜),说道: set 命令后面可以跟参数,实现加锁和设置过期时间两个操作,保证操作原子性。(命令:SET key value EX second NX

面试官微微一笑,嗯,还行

使用过 redis 做异步队列么?讲解一下实现方式

一般使用 list 结构做队列, lpush 生产消息, rpop 消费消息,当 rpop 没有消息的时候,适当的 sleep 一会儿再重试

面试官再问,可不可以不用 sleep 呢?

可以,使用 list 结构中的阻塞指令,如 brpop 。在列表没有元素时,会阻塞列表直到等待超时或发现可弹出元素为止。

再再追问,如果我想生产一次,消费多次呢?

可以使用 pub/sub 发布订阅模式 ,实现 1:N的消息队列

再再再追问,pub /sub 模式有什么缺点?

在消费者下线的情况下,生产的消息会丢失。可以使用专业的消息队列保证消息不丢失,如 rocketMQ、rabbitMQ

再再再再追问,Redis如何实现延时队列?

这个时候你可能会有想叫二营长把意大利炮拉上来的冲动。但是为了面试顺利,还是得强压内心的冲动,保持微笑

缓缓答道:使用 sortedset,用时间戳作为 score,消息内容作为 key,生产者调用 zadd 生产消息,消费者用 zrangebyscore 指令获取N秒之前的消息,轮询进行处理

Redis事务了解吗,如果事务中有某条/某些命令执行失败了会怎么样呢?

事务中的某条命令执行失败了,事务中的其他指令依然会继续执行。另外,Redis 事务不支持 roolback

假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如何将它们全部找出来?

使用 keys 指令可以扫出指定模式的key列表。

如果这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题?

这个时候你要回答redis关键的一个特性:redis是单线程的。 roolback keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用 scan 指令, scan 指令可以无阻塞的提取出指定模式的 key 列表,但是 key 可能会有一定的重复,在客户端做一次去重就可以了。 scan 整体所花费的时间会比用 keys 指令长。

MySQL里有2000w数据,redis中只能存20w的数据,如何保证redis中的数据都是热点数据?

当客户端往 Redis 添加了新的数据后。Redis 会检查内存使用情况,如果大于 maxmemory 的限制, 则根据设定好的淘汰策略对旧数据进行回收。

使用过Redis集群吗,集群的高可用怎么保证,集群的原理是什么?

Redis Sentinal(哨兵)着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。

Redis Cluster(集群)着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。

说说 Redis 集群的数据分片

Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念。Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。

面试结束

小伙子挺不错啊,什么时候有时间来上班呢?要不就明天吧。

你强装镇定:这么急啊,我还要租房。要不下周一吧

面试官心想,这么NB,可不能让他跑了,马上叫 HR 给他加钱

写在最后

不知你会不会有那样一种感觉,很多事情看起来很简单,觉得自己也能做,只是懒得去做而已;很多知识点看起来自己都知道,但当面试官问的时候,你却不能逻辑清晰且完整的做出回答,事后还觉得:这些自己都会,只是发挥不好而已…

我以前也是这样。但我现在才明白,其实不是懒,只是不想承认自己是个废物而已。多做、多思考、多总结吧!朋友

Stay hungry, stay foolish
努力提升自己技术的看度和广度,是通过面试的必要条件
平时多思考、多总结,才能在面试时侃侃而谈
另外保持自信和从容,会让你看起来更加靠谱,提升面试通过率

本文是根据平时面试的经历,总结完善而成。由于篇幅原因,有一些回答或许不够完美,我会在之后的文章中将面试时的常考点更加细致的剖析。

最后,祝大家早日上岸。咱们的口号是: 必拿下!!!

你的 点赞 关注 对我非常有用

猜你喜欢

转载自blog.csdn.net/weixin_39815001/article/details/108709773