既然我们前面聊到了什么是redisredis有什么用以及redis里面有很多的数据结构我有个疑惑就是redis快仅仅是因为它将数据存储在内存当中吗请你回答一下 redis为什么快这里就会引入IO多路复用技术是什么IO多路复用技术的主要作用是什么怎么实现的那redis是从哪一个版本开始引入IO多路复用技术的呢你能不能说一下IO多路复用技术的底层实现机制是什么你能不能说一下redis中的单线程和多线程Redis 为什么快呢第一redis将数据保存在内存当中内存的响应速度是非常快的通常是可以达到微秒级第二Redis 采用了基于IO多路复用技术的事件驱动模型来处理 客户端请求和执行 Redis 命令。其中的 IO 多路复用技术可以在只有一个线程的情况下同时监听成千上万个客户端连接解决传统 IO 模型中每个连接都需要一个独立线程带来的性能开销。IO 多路复用会持续监听请求然后把准备好的请求压入到一个队列当中并将其有序地传递给文件事件分派器最后由事件处理器来执行对应的 accept、read 和 write 请求。第三Redis 对底层数据结构做了极致的优化比如说 String 的底层数据结构动态字符串支持动态扩容、预分配冗余空间能够减少内存碎片和内存分配的开销。可能的几个追问点因为前面我们聊过redis的数据是保存在内存当中的这个地方就不做过多的赘述主要是还是将redis和MySQL来做一个对比的方式来进行考察接着就是redis用到了IO多路复用技术这个话会考察如果上面没有答到IO多路复用技术可以同时监听上万个客户端连接解决传统IO模型当中每一个连接都需要一个现成的开销问题的话这里就会被问到 您不能具体说一说IO多路复用技术可以实现哪些功能然后就是问你IO多路复用技术的底层原理底层的实现机制你到底了不了解IO多路复用技术是从哪一个版本开始引进的在引进之前MySQL是怎么实现对应的缓存机制的第三点的话就是我们前面提到过的数据结构的底层实现机制这个点还是非常重要的需要大家多花点时间去好好学习一下这部分的内容redis的IO复用技术是在哪一个版本进行引入的在 Redis 6.0 之前包括连接建立、请求读取、响应发送以及命令执行都是在主线程中顺序执行的这样可以避免多线程环境下的锁竞争和上下文切换因为 Redis 的绝大部分操作都是在内存中进行的性能瓶颈主要是内存操作和网络通信而不是 CPU。为了进一步解决网络IO的性能瓶颈Redis 6.0 引入了多线程机制把网络 IO 和命令执行分开网络 IO 交给线程池来处理而命令执行仍然在主线程中进行这样就可以充分利用多核 CPU 的性能。主线程专注于命令执行网络IO 由其他线程分担在多核 CPU 环境下Redis 的性能可以得到显著提升。碎碎念一下首先就是讲一讲redis的工作机制主要就是包括了连接建立建立完成连接之后就可以处理和读取请求根据请求内部的内容执行对应的命令命令的执行都是在主线程当中来完成的所以我们就可以去分析主要的性能瓶颈会出现在哪里网络连接的建立以及命令的执行部分了为什么不用多线程多线程存在的问题是你用多线程肯定得上锁吧所以会有多线程锁的竞争问题。多线程之间的上下文切换等问题既然你前面提到了IO多路复用技术有很大的作用那你能不能来详细的聊一聊IO多路复用技术能详细说一下IO多路复用吗IO 多路复用是一种允许单个进程同时监视多个文件描述符的技术使得程序能够高效处理多个并发连接而无需创建大量线程。IO 多路复用的核心思想是让单个线程可以等待多个文件描述符就绪然后对就绪的描述符进行操作。这样可以在不使用多线程或多进程的情况下处理并发连接。主要的实现机制包括 select、poll、epoll、kqueue 和 IOCP 等。底层的实现机制主要有5种重点还是掌握前面的前三种后面两种做一个了解。请说说 select、poll、epoll、kqueue 和 IOCP 的区别select 的缺点是单个进程能监视的文件描述符数量有限一般为 1024 个且每次调用都需要将文件描述符集合从用户态复制到内核态然后遍历找出就绪的描述符性能较差。poll 的优点是没有最大文件描述符数量的限制但是每次调用仍然需要将文件描述符集合从用户态复制到内核态依然需要遍历性能仍然较差。epoll 是Linux 特有的IO多路复用机制支持大规模并发连接使用事件驱动模型性能更高。其工作原理是将文件描述符注册到内核中然后通过事件通知机制来处理就绪的文件描述符不需要轮询也不需要数据拷贝更没有数量限制所以性能非常高。kqueue 是 BSD/macOS系统下的IO多路复用机制类似于 epoll支持大规模并发连接使用事件驱动模型。IOCP 是 Windows 系统下的 IO 多路复用机制使用使用完成端口模型而非事件通知。大概有个印象就是 select和poll的机制是怎么实现的两者的缺点是什么然后要了解到为什么 epoll的性能和实现的机制要比select和poll要好的多emmmmm你既然提到了他们5种不同的工作机制各自是怎么发挥作用的那你能不能说说前三种的底层实现原理呢select、poll 和 epoll 的实现原理select 和 poll 都是通过把所有文件描述符传递给内核由内核遍历判断哪些就绪。select 将文件描述符 FD 通过BitsMap 传入内核轮询所有的 FD通过调用 file-poll 函数查询是否有对应事件没有就将 task 加入 FD 对应 file 的待唤醒队列等待事件来临被唤醒。poll 改进了连接数上限问题不再用 BitsMap 来传入 FD取而代之的是动态数组pollfd但本质上仍是线性遍历性能没有提升太多。select和poll的模式都是一次将参数拷贝到内核空间等有结果了再一次拷贝出去。epoll 将监听的 FD 注册进内核的红黑树由内核在事件触发时将就绪的 FD 放入 ready list。应用程序通过 epoll_wait 获取就绪的 FD从而避免遍历所有连接的开销。epoll 最大的优点是支持事件驱动 边缘触发ADD 时拷贝一次epoll_wait 时利用 MMAP 和用户共享空间直接拷贝数据到用户空间因此在高并发场景下性能远高于 select 和 poll。那你能不能说一下早期的redis为什么使用单线程单线程的好处在哪里Redis为什么早期选择单线程第一单线程模型不需要考虑复杂的锁机制不存在多线程环境下的死锁、竞态条件等问题开发起来更快也更容易维护。第二Redis 是IO密集型而非 CPU 密集型主要受内存和网络 IO 限制而非 CPU 的计算能力单线程可以避免线程上下文切换的开销。哪怕我们在一个普通的 Linux 服务器上启动 Redis 服务它也能在 1s 内处理 1000000 个用户请求。第三单线程可以保证命令执行的原子性无需额外的同步机制。Redis 虽然最初采用了单线程设计但后续的版本中也在特定方面引入了多线程比如说 Redis 4.0 就引异步多线程用于清理脏数据、释放无用连接、删除大 Key 等。诶你前面提到了redis的多线程那这是怎么回事有没有可能会出现死锁的问题Redis 6.0 使用多线程是怎么回事?Redis 6.0 的多线程仅用于处理网络IO包括网络数据的读取、写入以及请求解析。而命令的执行依然是单线程这种设计被称为“IO线程化”能够在高负载的情况下最大限度地提升 Redis 的响应速度。单线程的Redis QPS 能到多少(补充)根据官方的基准测试一个普通服务器的 Redis 实例通常可以达到每秒十万左右的 QPS。Redis 的 QPS每秒请求数性能取决于多种因素包括硬件配置、网络延迟、数据结构、命令类型等。