引言
在互联网电商热火朝天倒退的大背景下,传统的关系型数据库(MySQL、Oracle)未然无奈满足高并发、限时秒杀等简单的场景。此时 NoSQL(非关系型数据库)应运而生,而 Redis 就是 NoSQL 大军里的一颗璀璨新星,在大厂面试中也是相对绕不开的话题。
面试开始
> 同学你好,先简略做个主动介绍吧?
面试官您好,我叫少侠露飞,……,纯熟使用 Redis、RocketMQ 等中间件。很期待退出贵部门。
> 好的,我看你自我介绍时提到了 Redis,你们我的项目里为何采纳 Redis,或者说你们是基于什么场景利用 Redis 的呢?
什么?心里忍不住暗骂,这叫啥问题,大家都在用,我就是为了用而用。然而咱们必定不能把实在想法说进去,做人当然要有点外延嘛。
于是认真答道:“闪闪发光”的面试官您好,因为传统的 MySQL 数据库曾经不能实用所有的场景了,比方限时秒杀,大流量削峰等,这些场景刹时流量可达到数万甚至数十万级,这些服务全部打到 MySQL,数据库必然扛不住,很容易被打崩造成服务宕机,所以引入了缓存中间件。在缓存中间件畛域有 Redis 和 Memcached 两个领头羊,然而 Redis 反对更多的数据类型,所以在综合思考之后抉择了 Redis。
> 嗯,答得不错,你刚刚提到了数据类型,那介绍一下 Redis 有哪些数据类型及相应的应用场景吧?
string(字符串),hash(哈希),list(列表),set(汇合)及 zset(sorted set:有序汇合)
数据类型 | 特点 | 应用场景 |
---|---|---|
string | key-value | 1. 缓存性能:Redis 作为缓存层,MySQL 作为存储层,减速读写并升高后端压力;2. 计数器性能,如视频点击量、文章浏览量等 |
hash | key-field-value | 假如要存储的对象有很多属性,那么为了示意该对象,必然有很多 Key 来形容该对象,然而接下来如果我批改某个值,还要把这个对象取出来再批改,比拟麻烦,所以就有了 Hash |
list | key-value,在一个 list 首端或末端增加元素 | 在朋友圈、微博等交友平台的发帖、回复、点赞、查看某一帖子点赞数等 |
set | 数据无序且不能反复 | set 能够做并集、交加运算,所以在独特好友、二度好友举荐场景下使用较多 |
zset | 数据有序,给每个 member 一个分数值,可反对按分数排序 | 微博等网站的排行榜 |
阐明了这五种根本数据类型并详细分析了各自的利用场景,千万不要洋洋自得甚至都要被本人折服了,因为这仅仅是合格。
你想从数千个竞争者中怀才不遇,必定要有些货色,你还须要补充说到这三种数据结构:<font color=”#E96900″>HyperLogLog、Geo、Pub/Sub</font>
这里我用一个理论的场景阐明一下 HyperLogLog。在电商畛域,常常要统计某一页面的 PV/UV(别离是浏览次数、浏览人数)。统计 UV 时必定要思考到去重,即同一个用户一天内无论点击多少次,都只算作一次。这个时候HyperLogLog 就能够一展能为了。HyperLogLog是基于基数统计,通过 hash 碰撞实现,用户 Id 通过给定的 hash 算法每次都会失去同样的值,在哈希桶的同一索引地位。当然统计 UV 不必 HyperLogLog 也是能够的,就用 set 或者 string(须要用到 setnx
)类型一样可行,这个不急,待会面试官就会问到。
须要留神的是,统计每天的 UV,相干的键须要设置当天过期,不然你会发现之后每天的 UV 数据都是异样的。
> 嗯,小伙子对 Redis 的数据结构把握的还不错(心田曾经给你比起了大拇指),刚刚你有提到setnx
,能够简略说说这个原理及用途么?
<font color=”#E96900″> 面试相对不要让本人处于齐全被动的位置。不知聪慧的你们发现了没有,面试官问的 Redis、setnx 等问题都是我先在答复中提到的,也就是说面试官能够自在提问,我也能够被动的在答复中提到一些知识点,疏导面试官询问相干,化被动为被动。这样就尽可能的把面试管制在咱们的节奏中。</font>
答复面试官的问题:setnx
经常用作分布式锁,setnx
核心思想在于争抢锁,抢到之后执行相干逻辑,留神执行完之后不要遗记用 expire
给锁设置一个过期工夫。
> 接着面试官开始下一轮的守势,问到如果在 setnx 后再执行 expire 期间过程意外 crash 或者服务重启保护了,那怎么办?
这个时候你要立刻做出回应:当这种状况 setnx 的锁就永远不会被开释了,这是个危险的操作。
而后稍加思考并给出解决方案:Redis 的 set 蕴含了丰盛的指令参数,这两个命令能够合并成一条命令变为 原子操作
来执行。
> 面试官曾经晓得背后的小伙不简略,于是决定加大难度:如果 Redis 外面有十亿个 key,其中有 10w 是以固定已知前缀结尾的,如何将它们找进去?
应用 keys
指令能够扫出指定模式的 key 列表。
到这里你还能够更秀一点。
你接着补充到,然而因为 Redis 是单线程模型,如果 Redis 正在给线上提供服务,keys
指令会导致线程阻塞一段时间,线上服务会进展。这个时候能够应用 scan
指令,scan
指令能够无阻塞的提取出指定模式的 key 列表,然而会有肯定的反复概率,将返回后果手动去重就行了。
> 这个时候面试官曾经克制不住冲动的情绪了,都学会抢答了,这个小伙子挺有料啊。既然刚刚提到了 Redis 的线程模型,能够说下么?
这个时候不要慌,稳稳的答道:Redis 是单线程模型,底层是 I / O 多路复用(对于此知识点我将会在 Nginx 的事件驱动模块做具体介绍)。
> 此时面试官曾经感到背后的小伙不个别了,于是持续开怼:Redis 是一种内存数据库,数据如何长久化呢?
有两种形式:RDB 做镜像全量长久化,AOF 做增量长久化。因为 RDB 会消耗较长时间,难以做到实时长久化,在停机的时候会导致大量失落数据,所以须要 AOF 来配合应用。在 Redis 实例重启时,会应用 RDB 长久化文件从新构建内存,再应用 AOF 重放近期的操作指令来实现残缺复原重启之前的状态。
这里很好了解,把 RDB 了解为一整个表全量的数据,AOF 了解为每次操作的日志就好了,服务器重启的时候先把表的数据全副塞进内存,然而他可能不残缺,你再回访一下日志,数据不就残缺了嘛。不过 Redis 自身的机制是 AOF 长久化开启且存在 AOF 文件时,优先加载 AOF 文件;AOF 敞开或者 AOF 文件不存在时,加载 RDB 文件;加载 AOF/RDB 文件之后,Redis 启动胜利;AOF/RDB 文件存在谬误时,Redis 启动失败并打印错误信息。
> 长久化的时候忽然断电了会怎么?
会失落数据,但这取决于 AOF 日志 sync 属性的配置,如果不要求性能,在每条写指令时都 sync 一下磁盘,就不会失落数据。然而在高性能的要求下每次都 sync 是不事实的,个别都应用定时 sync,比方 5s1 次,这个时候最多就会失落 5s 的数据。
> 面试官此时决定跟你卯上了,接着诘问:RDB 的原理呢?
这里有两个要害的步骤:fork 和 COW。fork 是指 Redis 通过创立子过程来进行 RDB 操作,COW 指的是 copy on write,子过程创立后,父子过程共享数据段,父过程持续提供读写服务,写脏的页面数据会逐步和子过程拆散开来。
注:答复这个问题的时候,如果你还能说出 AOF 和 RDB 的优缺点,我感觉面试官都会为你点赞的,对于此点我会在之后的博客持续补充。
> 既然在这类问题难不倒你,聪慧的面试官决定换个方向问你:应用过 Redis 做异步队列么,怎么用的?
面试官千方百计的想问倒咱们,咱们就凭借满腹经纶化解一次次的危机,所谓振长策而于宇内,奥利给…
认真答道:Redis 中个别用 list 数据结构作为异步队列,用 rpush
生产音讯,lpop
生产音讯。当消费者 lpop
发现没有音讯的时候要睡眠 sleep
一会再重试。
此时你再补充说道:除了应用sleep
,list 还有个指令叫blpop
,在没有音讯的时候,它会阻塞直到有新的音讯到来。
> 这个时候面试官会感觉你这小伙子对 Redis 的见解很独到,在心里曾经录用你 100 次了。然而,外表上还是要沉稳,毕竟是久经沙场的老技术人了。问答持续:像刚刚那种模式,数据 blpop
之后别的消费者就生产不了了,如何实现生产一次生产屡次呢?
应用 pub/sub 主题订阅者模式,能够实现 1:N 的音讯队列。
> 那么 pub/sub 主题订阅者模式的毛病呢?
该模式有个问题在于消费者下线的时候,生产的音讯会失落,得应用业余的音讯队列 RocketMQ 或 Kafka。
> 如果面试官还不罢休,Redis 如何实现延时队列?
这一系列的连环提问,预计有急躁如你,也想把面试官打一顿:还有完没完了。疫情这么重大都不敢在里面吃,我得回家本人做饭,人家今天还要下班呢!
然而,为了大厂的 offer,小伙子还是克服一下,而后神态自若的答复道:应用有序汇合 sortedset(zset),以音讯内容作为 key,用工夫戳作为 score 来调用 zadd 命令生产音讯,消费者用 zrangebyscore 指令获取 N 秒之前的数据轮询进行生产。
> 答复到这里,面试官曾经为你竖起了大拇指,并且心里默默的给了你 A +,然而他还不肯进行,筛不筛选人才的无所谓,次要就想问倒你。于是吹响了下一轮防御的号角:晓得 pipeline 吗?
能够将屡次 IO 往返的工夫缩减为一次,不过有个前提是 pipeline 执行的指令之间没有因果相关性。
注:实际上应用 redis-benchmark 进行压测的时候能够发现影响 redis 的 QPS 峰值的一个重要因素是 pipeline 批次指令的数目。
> 理解过 Redis 的同步机制么?
Redis 能够应用主从同步,从从同步。第一次同步时,主节点做一次 bgsave,并同时将后续批改操作记录到内存 buffer,待实现后将 RDB 文件全量同步到复制节点,复制节点承受实现后将 RDB 镜像加载到内存。加载实现后,再告诉主节点将期间批改的操作记录同步到复制节点进行重放就实现了同步过程。后续的增量数据通过 AOF 日志同步即可,有点相似数据库的 binlog。
> 应用过 Redis 的集群么?如何保障集群的高可用?
Redis Sentinal(Redis 哨兵,这个我之后会独自写一篇博客介绍)
着眼于高可用,在 master 宕机时会主动将 slave 晋升为 master,持续提供服务。
Redis Cluster
着眼于扩展性,在单个 redis 内存不足时,应用 Cluster 进行分片存储。
面试完结
小伙子能够啊,我很称心,咱们部门就缺你这种人才,要不明天就把入职手续办了吧?
这个时候,你千万要稳住,按捺一下冲动无比的心田:这么急啊,疫情这么重大,房子不好找啊,要不下周一吧。
面试官一听,哎呀,这小伙子预计在手的 offer 不少啊,这种人才怎么能放过,不行,人事经理何在,加钱!!!
当这些问题你都一一答复上来了,你是不是都感觉本人很棒呢?
总结
在技术面试的时候,不论是 Redis 还是什么问题,如果你能举出理论开发过程的问题和播种会给面试官的印象分会加很多,答复逻辑性也要强一点,不要东一榔头西一棒子的,容易把本人都绕晕了。
并且面试不应该简略的一问一答,若能在问题之外扩散一些知识点,面试官会感觉你不只是一个会写代码的人,你逻辑清晰,你对技术选型,对中间件、对我的项目都有本人的了解和思考,心里天然会给你点赞的。