引言
在互联网电商热火朝天倒退的大背景下,传统的关系型数据库(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还是什么问题,如果你能举出理论开发过程的问题和播种会给面试官的印象分会加很多,答复逻辑性也要强一点,不要东一榔头西一棒子的,容易把本人都绕晕了。
并且面试不应该简略的一问一答,若能在问题之外扩散一些知识点,面试官会感觉你不只是一个会写代码的人,你逻辑清晰,你对技术选型,对中间件、对我的项目都有本人的了解和思考,心里天然会给你点赞的。