Redis(基础)

Redis  

1、看你简历上写了你项目里面用到了Redis,你们为啥用 Redis ?

心里忍不住暗骂,这叫啥问题,大家不都是用的这个嘛,但是你不能说出来。

认真回答道:帅气迷人的面试官您好,因为传统的关系型数据库如Mysql已经不能适用所有的场景了,比如秒杀的库存扣减,APP首页的访问流量高峰等等,都很容易把数据库打崩,所以引入了缓存中间件。

目前市面上比较常用的缓存中间件有 Redis 和 Memcached 不过中和考虑了他们的优缺点,最后选择了Redis。

至于更细节的对比朋友们记得查阅 Redis 和 Memcached 的区别,比如两者的优缺点对比和各自的场景。

 

2、我再问你,Redis有哪些数据结构呀?

String、Hash、List、Set、SortedSet。

这里我相信 99% 的读者都能回答上来Redis的5个基本数据类型。如果回答不出来的小伙伴我们就要加油补课哟,大家知道五种类型最适合的场景更好。

但是,如果你是Redis中高级用户,而且你要在这次面试中突出你和其他候选人的不同,还需要加上下面几种数据结构 HyperLogLog、Geo、Pub/Sub。

如果你还想加分,那你说还玩过 Redis Module,像 BloomFilter,RedisSearch,Redis-ML,这个时候面试官得眼睛就开始发亮了,心想这个小伙子有点东西啊。

 

3、如果有大量的 key 需要设置同一时间过期,一般需要注意什么?

如果大量的 key 过期时间设置的过于集中,到过期的那个时间点,Redis可能会出现短暂的卡顿现象。严重的话会出现缓存雪崩,我们一般需要在时间上加一个随机值,使得过期时间分散一些。

电商首页经常会使用定时任务刷新缓存,可能大量的数据失效时间都十分集中,如果失效时间一样,又刚好在失效的时间点大量用户涌入,就有可能造成缓存雪崩

 

4、那你使用过 Redis 分布式锁么,它是什么回事?

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

这时候对方会告诉你说你回答得不错,然后接着问如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?

这时候你要给予惊讶的反馈:唉,是喔,这个锁就永远得不到释放了。紧接着你需要抓一抓自己得脑袋,故作思考片刻,好像接下来的结果是你主动思考出来的,然后回答:我记得set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!

  1. SET lock_key random_value NX PX 5000
  2. random_value 是客户端生成的唯一的字符串。
  3. NX 代表只在键不存在时,才对键进行设置操作。
  4. PX 5000 设置键的过期时间为5000毫秒。

对方这时会显露笑容,心里开始默念:嗯,这小子还不错,开始有点意思了。

 

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

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

 

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

这个时候你要回答 Redis 关键的一个特性:Redis的单线程的。

keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。

这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长。

不过,增量式迭代命令也不是没有缺点的: 举个例子, 使用 SMEMBERS 命令可以返回集合键当前包含的所有元素, 但是对于 SCAN 这类增量式迭代命令来说, 因为在对键进行增量式迭代的过程中, 键可能会被修改, 所以增量式迭代命令只能对被返回的元素提供有限的保证 。

 

7、使用过Redis做异步队列么,你是怎么用的?

一般使用 list 结构作为队列,rpush 生产消息,lpop 消费消息。当 lpop 没有消息的时候,使用 sleep 持续继续重试。

 

8、如果对方追问可不可以不用sleep呢

list还有个指令叫blpop,在没有消息的时候,它会阻塞住直到消息到来。

 

9、如果对方接着追问能不能生产一次消费多次呢?

使用pub/sub主题订阅者模式,可以实现 1:N 的消息队列。

 

10、如果对方继续追问 pub/sub有什么缺点?

在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如 RocketMQ 等。

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

 

11、继续追问 Redis如何实现延时队列

使用有序集合 zset,拿时间戳作为score,消息内容作为 key 调用zadd来生产消息,消费者用zrangebyscore指令获取 N 秒之前的数据轮询进行处理。

到这里,面试官暗地里已经对你竖起了大拇指。并且已经默默给了你A+,但是他不知道的是此刻你却竖起了中指,在椅子背后。

 

12、Redis 是怎么持久化的?主从数据怎么交互的?

在 Redis 4.0 以后,默认采取 RDB-AOF 混合持久化方式。RDB 做镜像全量持久化,AOF做增量持久化。

主从数据的交互,可以参考 https://www.haveyb.com/article/173

 

13、对方追问那如果突然机器断电会怎样?

取决于 AOF 日志 sync 属性的配置,如果不要求性能,在每条写指令时都 sync一下磁盘,就不会丢失数据。

但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s1次,这个时候最多就会丢失1s的数据。

 

14、对方追问 RDB 的原理是什么?

Redis 调用 fork() ,同时拥有父进程和子进程。

子进程将数据集写入到一个临时 RDB 文件中

当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。

这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益。

注:AOF 与 RDB 的优缺点

 

15、Pipeline有什么好处,为什么要用pipeline?

可以将多次 IO 往返的时间缩减为一次,前提是 pipeline 执行的指令之间没有因果相关性。

使用redis-benchmark进行压测的时候可以发现影响 redis 的 QPS 峰值的一个重要因素是 pipeline 批次指令的数目。

 

16、Redis的同步机制了解么?

Redis可以使用主从同步,从从同步。第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将RDB文件全量同步到复制节点,复制节点接受完成后将RDB镜像加载到内存。

加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。后续的增量数据通过AOF日志同步即可,有点类似数据库的binlog。

 
原文链接:https://juejin.im/post/5db66ed9e51d452a2f15d833



Top