面试被吊打 - Redis原理

小张兴冲冲去面试,结果被面试官吊打!

小张:java

面试官,你好。我是来参加面试的。程序员

面试官:web

你好,小张。我看了你的简历,熟练掌握Redis,那么我就随便问你几个Redis相关的问题吧。首先个人问题是,Redis是单线程仍是多线程呢?面试

小张:redis

Redis不一样版本之间采用的线程模型是不同的,在Redis4.0版本以前使用的是单线程模型,在4.0版本以后增长了多线程的支持。算法

在4.0以前虽然咱们说Redis是单线程,也只是说它的网络I/O线程以及Set 和 Get操做是由一个线程完成的。可是Redis的持久化、集群同步仍是使用其余线程来完成。数据库

4.0以后添加了多线程的支持,主要是体如今大数据的异步删除功能上,例如 unlink keyflushdb asyncflushall async服务器

面试官:微信

回答的很好,那为何Redis在4.0以前会选择使用单线程?并且使用单线程还那么快?网络

小张:

选择单线程我的以为主要是使用简单,不存在锁竞争,能够在无锁的状况下完成全部操做,不存在死锁和线程切换带来的性能和时间上的开销,但同时单线程也不能彻底发挥出多核CPU的性能。

至于为何单线程那么快我以为主要有如下几个缘由:

  1. Redis 的大部分操做都在内存中完成,内存中的执行效率自己就很快,而且采用了高效的数据结构,好比哈希表和跳表。
  2. 使用单线程避免了多线程的竞争,省去了多线程切换带来的时间和性能开销,而且不会出现死锁。
  3. 采用 I/O 多路复用机制处理大量客户端的Socket请求,由于这是基于非阻塞的 I/O 模型,这就让Redis能够高效地进行网络通讯,I/O的读写流程也再也不阻塞。

面试官:

不错,那Redis是如何实现数据不丢失的呢?

小张:

Redis数据是存储在内存中的,为了保证Redis数据不丢失,那就要把数据从内存存储到磁盘上,以便在服务器重启后还可以从磁盘中恢复原有数据,这就是Redis的数据持久化。Redis数据持久化有三种方式。

  • AOF 日志(Append Only File,文件追加方式):记录全部的操做命令,并以文本的形式追加到文件中。
  • RDB 快照(Redis DataBase):将某一个时刻的内存数据,以二进制的方式写入磁盘。
  • 混合持久化方式:Redis 4.0 新增了混合持久化的方式,集成了 RDB 和 AOF 的优势。

面试官:

那你分别说说 AOF和 RDB的实现原理吧。

小张:

AOF采用的是写后日志的方式,Redis先执行命令把数据写入内存,而后再记录日志到文件中。AOF日志记录的是操做命令,不是实际的数据,若是采用AOF方法作故障恢复时须要将全量日志都执行一遍。

RDB采用的是内存快照的方式,它记录的是某一时刻的数据,而不是操做,因此采用RDB方法作故障恢复时只须要直接把RDB文件读入内存便可,实现快速恢复。

面试官:

你刚提到了AOF采用的是 “写后日志” 的方式,咱们平时用的MySQL则采用的是 “写前日志”,那 Redis为何要先执行命令,再把数据写入日志呢?

小张:额头开始冒汗,问的是些啥问题呀。。。

额,这个主要是因为Redis在写入日志以前,不对命令进行语法检查,因此只记录执行成功的命令,避免出现记录错误命令的状况,并且在命令执行后再写日志不会阻塞当前的写操做。

面试官:

后写日志又有什么风险呢?

小张:

我... 这个我不会。

面试官:

好吧,后写日志主要有两个风险可能会发生:

  • 数据可能会丢失:若是 Redis 刚执行完命令,此时发生故障宕机,会致使这条命令存在丢失的风险。
  • 可能阻塞其余操做:AOF 日志其实也是在主线程中执行,因此当 Redis 把日志文件写入磁盘的时候,仍是会阻塞后续的操做没法执行。

我还有个问题是 RDB作快照时会阻塞线程吗?

小张:

Redis 提供了两个命令来生成 RDB 快照文件,分别是 savebgsavesave 命令在主线程中执行,会致使阻塞。而 bgsave 命令则会建立一个子进程,用于写入 RDB 文件的操做,避免了对主线程的阻塞,这也是 Redis RDB 的默认配置。

面试官:

RDB 作快照的时候数据能修改吗?

小张:

save是同步的会阻塞客户端命令,bgsave的时候是能够修改的。

面试官:

那Redis是怎么解决在bgsave作快照的时候容许数据修改呢?

小张:(你咋还问。。。我™不会啊!)

额,这个我不太清楚...


面试官:

这里主要是利用 bgsave的子线程实现的,具体操做以下:

  • 若是主线程执行读操做,则主线程和 bgsave 子进程互相不影响;
  • 若是主线程执行写操做,则被修改的数据会复制一份副本,而后 bgsave子进程会把该副本数据写入 RDB 文件,在这个过程当中,主线程仍然能够直接修改原来的数据。


要注意,Redis 对 RDB 的执行频率很是重要,由于这会影响快照数据的完整性以及 Redis 的稳定性,因此在 Redis 4.0 后,增长了 AOF 和 RDB 混合的数据持久化机制: 把数据以 RDB 的方式写入文件,再将后续的操做命令以 AOF 的格式存入文件,既保证了 Redis 重启速度,又下降数据丢失风险。

小张:

学到了学到了。

面试官:

那你再跟我说说Redis如何实现高可用吧?

小张:

Redis实现高可用主要有三种方式:主从复制、哨兵模式,以及 Redis 集群。

主从复制

将从前的一台 Redis 服务器,同步数据到多台从 Redis 服务器上,即一主多从的模式,这个跟MySQL主从复制的原理同样。


哨兵模式

使用 Redis 主从服务的时候,会有一个问题,就是当 Redis 的主从服务器出现故障宕机时,须要手动进行恢复,为了解决这个问题,Redis 增长了哨兵模式(由于哨兵模式作到了能够监控主从服务器,而且提供自动容灾恢复的功能)。


Redis Cluster(集群)

Redis Cluster 是一种分布式去中心化的运行模式,是在 Redis 3.0 版本中推出的 Redis 集群方案,它将数据分布在不一样的服务器上,以此来下降系统对单主节点的依赖,从而提升 Redis 服务的读写性能。


面试官:

使用哨兵模式在数据上有副本数据作保证,在可用性上又有哨兵监控,一旦master宕机会选举salve节点为master节点,这种已经知足了咱们的生产环境须要,那为何还须要使用集群模式呢?

小张:

额,哨兵模式归根节点仍是主从模式,在主从模式下咱们能够经过增长slave节点来扩展读并发能力,可是没办法扩展写能力和存储能力,存储能力只能是master节点可以承载的上限。因此为了扩展写能力和存储能力,咱们就须要引入集群模式。

面试官:

集群中那么多Master节点,redis cluster在存储的时候如何肯定选择哪一个节点呢?

小张:

这应该是使用了某种hash算法,可是我不太清楚。。。


面试官:

那好,今天的面试就到这里吧,你先回去等咱们的面试通知。

小张:

好的,谢谢面试官,你能告诉我redis cluster怎么实现节点选择的吗?

面试官:

Redis Cluster采用的是类一致性哈希算法实现节点选择的,至于什么是一致性哈希算法你本身回去看看。

Redis Cluster将本身分红了16384个Slot(槽位),哈希槽相似于数据分区,每一个键值对都会根据它的 key,被映射到一个哈希槽中,具体执行过程分为两大步。

  • 根据键值对的 key,按照 CRC16 算法计算一个 16 bit 的值。
  • 再用 16bit 值对 16384 取模,获得 0~16383 范围内的模数,每一个模数表明一个相应编号的哈希槽。

每一个Redis节点负责处理一部分槽位,假如你有三个master节点 ABC,每一个节点负责的槽位以下:

节点 处理槽位
A 0-5000
B 5001 - 10000
C 10001 - 16383

这样就实现了cluster节点的选择。

好了,各位看官朋友们,Redis原理的这些面试点大家记住了吗?但愿大家的面试不会被这个问题难倒哟~



End




干货分享



这里为你们准备了一份小小的礼物,关注公众号,输入以下代码,便可得到百度网盘地址,无套路领取!

001:《程序员必读书籍》
002:《从无到有搭建中小型互联网公司后台服务架构与运维架构》
003:《互联网企业高并发解决方案》
004:《互联网架构教学视频》
006:《SpringBoot实现点餐系统》
007:《SpringSecurity实战视频》
008:《Hadoop实战教学视频》
009:《腾讯2019Techo开发者大会PPT》

010: 微信交流群






近期热文top



一、关于JWT Token 自动续期的解决方案

二、SpringBoot开发秘籍-事件异步处理

三、架构师之路-服务器硬件扫盲

四、基于Prometheus和Grafana的监控平台 - 环境搭建

五、RocketMQ进阶 - 事务消息



我就知道你“在看”


本文分享自微信公众号 - JAVA日知录(javadaily)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索