【搞定面试官】系列:Redis基础

引言

在互联网电商如火如荼发展的大背景下,传统的关系型数据库(MySQL、Oracle)已然没法知足高并发、限时秒杀等复杂的场景。此时NoSQL(非关系型数据库)应运而生,而Redis就是NoSQL大军里的一颗璀璨新星,在大厂面试中也是绝对绕不开的话题。面试

面试开始

> 同窗你好,先简单作个自动介绍吧?

面试官您好,我叫少侠露飞,……,熟练运用Redis、RocketMQ等中间件。很期待加入贵部门。redis

> 好的,我看你自我介绍时提到了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仍是什么问题,若是你能举出实际开发过程的问题和收获会给面试官的印象分会加不少,回答逻辑性也要强一点,不要东一榔头西一棒子的,容易把本身都绕晕了。
而且面试不该该简单的一问一答,若能在问题以外扩散一些知识点,面试官会以为你不仅是一个会写代码的人,你逻辑清晰,你对技术选型,对中间件、对项目都有本身的理解和思考,内心天然会给你点赞的。

点点关注,不会迷路

相关文章
相关标签/搜索