决战紫禁之巅之Redis面试

Redis单线程为什么那么快?

redis的速度非常快,速度快的原因主要有以下几点:

  1. 完全基于内存操作
  2. C语言实现,优化过的数据结构,基于几种基础的数据结构,redis做了大量的优化,性能极高
  3. 使用单线程,无上下文的切换成本
  4. 基于非阻塞的IO多路复用机制

请说说常用的Redis基本类型

类型 底层实现 场景
String (字符串) SDS动态字符串,小于多少的时候是采用压缩存储的 1.验证码时间判断 2.分布式锁,3.去重等
List(链表结构,双向链表) LinkedLIst双端队列,zip压缩链表 1.数据的延迟加载效果,2.消息队列
Hash(参考HashMap,键值对) zip压缩链表,哈希表 1.购物车,2.用户信息等
Set(元素集合不能重复) 哈希表,字典 1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐
Sorted Set(有序集合) zip压缩链表,跳跃表[skiplist] 1、排行榜 ,2.延迟消息队列

Redis不是单线程?Redis6.0为什么采用了多线程?

redis认为性能瓶颈在于网络IO而非CPU,使用多线程能提升IO读写的效率,从而整体提高redis的性能,处理客户端请求依然是单线程。

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

这个考察的就是热点key问题,

热点key问题就是某一时间段,很多请求去请求某一个key,造成该流量高峰,导致Redis雪崩造成宕机

怎么解决呢

  1. 提前把热key打散到不同的服务器,降低压力
  2. 加入二级缓存,提前加载热key数据到内存中,如果redis宕机,走内存查询,二级缓存很多如Ehcache,Caffeine 都可以去看看

经典三大问题:缓存击穿、缓存穿透、缓存雪崩?

缓存击穿

缓存击穿的概念就是单个key并发访问过高,过期时导致所有请求直接打到db上,这个和热key的问题比较类似,只是说的点在于过期导致请求全部打到DB上而已。

解决方案:

  1. 加锁更新,当来了一个请求,发现缓存中没有,我们就对这个请求的这个key加锁,同时去数据库查询数据,写入缓存,再返回给用户,这样后面的请求就可以从缓存中拿到数据了。

缓存穿透

缓存穿透是指查询不存在缓存中的数据,每次请求都会打到DB,就像缓存不存在一样。

解决方案:

1,缓存一个过期时间短的空值,这样当数据不存在的时候还是走的是Redis没有全部请求打到数据中

2,针对这个问题,Redis提供了布隆过滤器。布隆过滤器的原理是在你存入数据的时候,会通过散列函数(多次不同的Hash方法)将它映射为一个位数组中的K个点,同时把他们置为1。这样当用户再次来查询A,而A在布隆过滤器值为0,直接返回,就不会产生击穿请求打到DB了。显然,使用布隆过滤器之后会有一个问题就是误判,因为它本身是一个数组,可能会有多个值落到同一个位置,那么理论上来说只要我们的数组长度够长,误判的概率就会越低,布隆过滤器也可以自定义参数,减少误判率增加布隆过滤器的长度,浪费了内存,这个看实际情况怎么衡量了

缓存雪崩

当某一时刻发生大规模的缓存失效的情况,比如你的缓存服务宕机了,会有大量的请求进来直接打到DB上,这样可能导致整个系统的崩溃,称为雪崩。雪崩和击穿、热key的问题不太一样的是,雪崩是指大规模的缓存都过期失效了。

解决方案:

  1. 既然是同一时间过期导致的,我们就对不同key设置不同的过期时间,避免同时过期
  2. 二级缓存,雪崩也是大量key失效导致请求都去请求数据库了,二级缓存预先加载,我们加二级缓存当Redis中没有就走本地缓存查询

Redis的过期策略有哪些?

redis主要有2种过期删除策略

惰性删除

惰性删除指的是当我们查询key的时候才对key进行检测,如果已经达到过期时间,则删除。这个跟我们前面讲的Redis渐进式Hash是否相似查到了就移动到新的字典中,但是Redis的渐进式hash会有定时任务定时移动旧字典的key到新字典中,而惰性删除没有定时删除,所以惰性删除当没有访问到的key就会一直占用内存,浪费内存

惰性删除.png

定期删除

我们上面才说了Redis不会定期删除,啪啪啪的打脸了,

Redis的定期删除指的是redis每隔一段时间对数据库做一次检查,删除里面的过期key。由于不可能对所有key去做轮询来删除,所以redis会每次随机取一些key去做检查和删除。

Redis的拒绝策略

当上面俩种策略都没有删除redis的key的时候,这些key也没有走查询的话,就会导致这些key一直保存在redis里面无法被删除,这时候就会走到redis的内存淘汰机制。【特意列在一起了,好观察】

  1. volatile-lru:从已设置过期时间的key中,移出最近最少使用的key进行淘汰
  2. volatile-ttl:从已设置过期时间的key中,移出将要过期的key
  3. volatile-random:从已设置过期时间的key中随机选择key淘汰
  4. allkeys-lru:从key中选择最近最少使用的进行淘汰
  5. allkeys-random:从key中随机选择key进行淘汰
  6. noeviction:当内存达到阈值的时候,新写入操作报错

Redis4.0新增加了俩种拒绝策略(LFU算法淘汰)

  • volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少的键
  • allkeys-lfu:从所有键中驱逐使用频率最少的键

持久化方式有哪些?有什么区别?

redis持久化方案分为RDB和AOF两种。

RDB

RDB持久化可以手动执行也可以根据配置定期执行,它的作用是将某个时间点上的数据库状态保存到RDB文件中,RDB文件是一个压缩的二进制文件,通过它可以还原某个时刻数据库的状态。由于RDB文件是保存在硬盘上的,所以即使redis崩溃或者退出,只要RDB文件存在,就可以用它来恢复还原数据库的状态。

可以通过SAVE或者BGSAVE来生成RDB文件。

SAVE命令会阻塞redis进程,直到RDB文件生成完毕,在进程阻塞期间,redis不能处理任何命令请求,阻塞的持久化方式策略就不适合,

BGSAVE则是会fork出一个子进程,然后由子进程去负责生成RDB文件,父进程还可以继续处理命令请求,不会阻塞进程。

#Redis的RDB配置的持久化策略
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。

save 300 10  #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。
 
save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。

AOF

AOF是通过保存redis服务器所执行的写命令来记录数据库状态的。

AOF通过追加、写入、同步三个步骤来实现持久化机制。

  1. 选择了Aof的持久化策略,服务器执行完写命令之后,
  2. 在服务器每结束一个事件循环之前,将会调用flushAppendOnlyFile函数决定是否要将aof_buf的内容保存到AOF文件中,可以通过配置appendfsync来决定。
#Aof默认关闭的 
appendonly yes #开启Aof
appendfsync always     #每次有数据修改发生时都会写入AOF文件。
appendfsync everysec  #每秒钟同步一次,该策略为AOF的缺省策略。
appendfsync no          #从不同步。高效但是数据不会被持久化。

如果不设置,默认选项将会是everysec,因为always来说虽然最安全(只会丢失一次事件循环的写命令),但是性能较差,而everysec模式只不过会可能丢失1秒钟的数据,而no模式的效率和everysec相仿,但是会丢失上次同步AOF文件之后的所有写命令数据。

Redis的高可用方案你能说说?

Redis的高可用方案有俩种 Redis的哨兵方案跟集群方案,

主从架构

主从模式是最简单的实现高可用的方案,核心就是主从同步。主从同步的原理如下:

  1. 从服务器向主服务器发送SYNC命令。
  2. 收到SYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区记录从现在开始执行的所有写命令。
  3. 当主服务器的BGSAVE命令执行完毕,主服务器将生成的RDB文件发送给从服务器,从服务器接收并加载这个RDB文件,将自己的数据库状态更新至主服务器执行BGSAVE命令时的数据库状态。
  4. 主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库状态更新至主服务器当前所处的状态。

看过之前的文章都看到我上面写的是Redis2.8之前的主从同步操作,Redis2.8之后新引入了psync 命令

psync命令

PSYNC命令具有完全同步和部分重同步功能。

    完全同步跟sync是一样的,

    psync命令在断线后的重复制情况:当从服务器断开重新连接后,主服务器将断开期间的写命令发给从服务器,从服务器执行断开期间的写命令完成同步,将数据库更新到和主服务器一致。【这个阶段增量同步的队列是可用配置大小的,不知道请回看之前的文章】

Redis的哨兵

主从方案的缺点还是很明显的,假设master宕机,那么就不能写入数据,那么slave也就失去了作用,整个架构就不可用了,除非你手动切换,主要原因就是因为没有自动故障转移机制。而哨兵(sentinel)的功能比单纯的主从架构全面的多了,它具备自动故障转移、集群监控、消息通知等功能。

哨兵流程请参考原文章

redis集群的原理吗?

Redis集群还没有说过,这里我们就从为什么需要Redis集群讨论:

我们的Redis哨兵可实现高可用,而Redis称能到达10万的QPS,当请求多的时候这个QPS也抗不住了,那怎么保持又能高可用又能支持高并发呢?Redis集群就出来了

Redis集群是Redis提供的分布式数据存储方案,集群通过数据分片sharding来进行数据的共享,同时提供复制和故障转移的功能。

图中是不同请求落到Master的不同的主节点上,主节点之间的箭头表示节点间的心跳检测,

Redis集群原理.png

图中的请求都落到不同的Redis上面了,数据是怎么得到的?

Redis有一个slot插槽的概念【Redis Cluster 将所有数据划分为 16384 个 slots(槽位),每个节点负责其中一部分槽位。槽位的信息存储于每个节点中】,

讲到这里还是没有说清楚是怎么获取到其他节点的数据?只说了他把数据存储在哪?获取呢?

当客户端向一个节点发出获取指令,当该节点发现指令的 key 所在的槽位并不归自己管理,这时它会向客户端发送一个特殊的跳转指令携带目标操作的节点地址,告诉客户端去连这个节点去获取数据。客户端收到指令后除了跳转到正确的节点上去操作,还会同步更新纠正本地的槽位映射表缓存,后续所有 key 将使用新的槽位映射表

当对集群增加或者移出节点,对于slot的重新分配也是非常方便的,redis提供了工具帮助实现slot的迁移,整个过程是完全在线的,不需要停止服务。

Redis集群的故障转移

如果节点A向节点B发送ping消息,节点B没有在规定的时间内响应pong,那么节点A会标记节点B为pfail疑似下线状态,同时把B的状态通过消息的形式发送给其他节点,如果超过半数以上的节点都标记B为pfail状态,B就会被标记为fail下线状态,此时将会发生故障转移,优先从复制数据较多的从节点选择一个成为主节点,并且接管下线节点的slot,整个过程和哨兵非常类似,都是基于Raft协议做选举。

知道Redis事务机制吗?

参考以前的文章

进阶面试题:

  1. Redis的字符串小于多少的时候会采用压缩存储呢?
  2. Redis的哨兵集群是怎么通信的【Redis哨兵的时候讲了】
  3. Redis集群为什么至少需要三个master节点,并且推荐节点数为奇数呢【跟哨兵原理差不多】?
  4. 跳跃表数据结构也常考

【还有进阶的面试题欢迎补充,这几个面试题下次说】

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容