前言:此篇文章系本人学习过程中记录下来的笔记,里面难免会有不少欠缺的地方,诚心期待大家多多给予指教。
基础篇:
进阶篇:
接上期内容:上期完成了Redis基础篇的学习。下面开始学习Redis的进阶知识,话不多说,直接发车。
一、前提说明
进阶篇主要学习Redis面试中反复出现的经典问题以及与之紧密对应的实际操作。这一阶段的学习具有一定的挑战性,需要你具备扎实的Redis基础知识。如果你是零基础的新手,或者目前基础较为薄弱,建议你先移步基础篇。待你在基础篇中积累了足够的知识和经验,再信心满满地回归,向进阶篇发起冲击。
二、经典面试题
(一)、多线程 VS 单线程
1、Redis是多线程还是单线程
答:分版本讨论。
redis版本为3.x ,redis是单线程。
redis版本4.x,严格意义来说也不是单线程,而是负责处理客户端请求的线程是单线程,但是开始加了点多线程的东西(异步删除)。
2020年5月版本的6.0.x后及2022年出的7.0版本后,告别了大家印象中的单线程,用一种全新的多线程来解决问题

*总结:分版本讨论。Redis6.x之前都可以称单线程,Redis6.x之后是多线程(这个多线程主要是用于处理网络 I/O 操作,而键值对的读写操作仍然是单线程的)。
2、Redis的单线程指的什么?
答:Redis单线程指Redis的网络IO和键值对读写是由一个线程来完成的,Redis在处理客户端的请求时包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理,这就是所谓的“单线程”。这也是Redis对外提供键值存储服务的主要流程。

但Redis的其他功能,比如持久化RDB、AOF、异步删除、集群数据同步等等,其实是由额外的线程执行的。
*总结:单线程指的是Redis命令工作线程,但是,整个Redis(6.x之后)来说,是多线程的。
3、Redis4.x之前为啥选择单线程?
答:①、使用单线程模型是Redis的开发和维护更简单,因为单线程模型方便开发和调试。
②、单线程避免了不必要的上下文切换和多线程竞争,这就省去了多线程切换带来的时间和性能上的消耗,而且单线程不会导致死锁问题的发生。
③、即使使用单线程模型也并发的处理多客户端的请求,主要使用的是IO多路复用和非阻塞IO。
④、对于Redis系统来说,主要的性能瓶颈是内存或者网络带宽而并非 CPU。

4、既然单线程这么好,为啥又逐渐引入多线程?
答:单线程虽好,但也不是全能。正常情况下使用 del 指令可以很快的删除数据,而当被删除的 key 是一个非常大的对象时,例如时包含了成千上万个元素的 hash 集合时,那么 del 指令就会造成 Redis 主线程卡顿。这就是redis3.x单线程时代最经典的故障,大key删除的问题。
于是在 Redis 4.x 中就新增了多线程的模块,当然此版本中的多线程主要是为了解决删除数据效率比较低的问题的,比如unlink key、flushdb async、flushall async命令。
*总结:逐渐引入多线程是为了弥补单线程的短板,比如删除bigKey问题。
(二)、I/O多路复用
1、什么是I/O多路复用?
答:①、I/O一般在操作系统层面指数据在内核态和用户态之间的读写操作。
②、多路指多个客户端连接(连接就是套接字描述符,即 socket 或者 channel)。
③、复用指复用一个或几个线程
*总结:在Redis中的I/O多路复用指一个或一组线程处理多个TCP连接,使用单进程就能够实现同时处理多个客户端的连接,无需创建或者维护过多的进程/线程。
在Unix网络编程中的I/O多路复用指的是一种同步的IO模型,实现一个线程多个文件句柄,一旦某个文件句柄就绪就能够通知到对应应用程序进行相应的读写操作,没有文件句柄就绪时就会阻塞应用程序,从而释放CPU资源。

后续会深入研究。
2、主线程和IO线程如何协作完成请求?
答:
阶段一:服务端和客户端建立Socket连接,并分配处理线程
首先,主线程负责接收建立连接请求,当有客户端请求和实例建立Socket连接时,主线程会创建和客户端的连接,并把 Socket 放入全局等待队列中。紧接着,主线程通过轮询方法把Socket连接分配给IO线程。
阶段二:IO线程读取并解析请求
主线程一旦把 Socket 分配给IO线程,就会进入阻塞状态,等待IO线程完成客户端请求读取和解析。因为有多个IO线程在并行处理,所以,这个过程很快就可以完成。
阶段三:主线程执行请求操作
等到IO线程解析完请求,主线程还是会以单线程的方式执行这些命令操作。
阶段四:IO线程回写 Socket 和主线程清空全局队列

最低0.47元/天 解锁文章
224

被折叠的 条评论
为什么被折叠?



