面试官:Redis 为什么可以抗高并发?
派大星:首先,Redis使用内存存储数据,避免了磁盘I/O的开销,提高了数据访问的速度。其次,Redis拥有丰富的对象类型,包含八种类型,满足不同的需求。此外,Redis采用了高效的数据结构,减少了内存占用和计算复杂度。Redis还使用单线程模型,避免了多线程之间的上下文切换和竞争条件,提升了CPU利用率。最后,Redis使用非阻塞I/O多路复用机制(多路复用IO模型实际也是传统阻塞型IO模型演化而来的),充分利用CPU和网络资源,提高了并发处理能力。
面试官:Redis 为什么使用单线程却依旧可以抗高并发?
面试官考察目的分析:
- 考察你对于Redis原理的理解程度;
- 考察你对于网络连接的理解程度;
派大星:首先Redis为什么选择单线程的实现方式:
- 从Redis自身特性来说,Redis是基于内存的数据库,所以数据处理速度非常快。另外它的底层使用了很多效率很高的数据结构,如哈希表和跳表等。另外Redis从狭义上面来说他是单线程的,网络请求解析与数据读写都是由主线程完成。因此它内部就省去了很多多线程访问共享数据资源的繁琐设计,同时也避免了频繁的线程上下文切换因此减少了多线程的系统开销。
派大星:Redis 为什么可以抗高并发。
- 其次从IO模型角度来说,Redis使用的是IO多路复用模型,使得它可以在网络IO操作并发处理数十万的客户端网络连接,实现非常高的网络吞吐率。这也是Redis可以实现高并发访问的最主要的原因。
还有一点就是常识问题:我们都知道磁盘的寻址是ms级别的,带宽是G/M(也就是千兆位每秒或兆位每秒)。而内存寻址是ns级别的,并且带宽远比磁盘快得多。从这个角度来看Redis基于内存的数据库快是毋庸置疑的。
面试官:刚才你提到了IO多路复用模型,其实也就是Redis 线程模型,能详细说下Redis的IO多路复用的原理吗?
派大星:好的。首先我们要明确知道Redis 服务器是一个事件驱动程序, 服务器处理的事件分为文件事件和时间事件两类。
- 文件事件:Redis 主进程中,主要处理客户端的连接请求与响应。
- 时间事件:fork 出的子进程中,处理如 AOF 持久化任务等。
派大星:之所以 Redis 的文件事件是单进程,单线程模型,但是确保持着优秀的吞吐量,IO 多路复用起到了主要作用。
- 文件事件是对套接字操作的抽象,每当一个套接字准备好执行连接应答、写入、读取、关闭等操作时,就会产生一个文件事件。因为一个服务器通常会连接多个套接字,所以多个文件事件有可能会并发地出现。
- IO 多路复用程序负责监听多个套接字并向文件事件分派器传送那些产生了事件的套接字。文件事件分派器接收 IO 多路复用程序传来的套接字,并根据套接字产生的事件的类型,调用相应的事件处理器。示例如图所示:
派大星:而Redis 的 IO 多路复用程序的所有功能都是通过包装常见的 select、poll、evport 和 kqueue 这些 IO 多路复用函数库来实现的,每个 IO 多路复用函数库在 Redis 源码中都有对应的一个单独的文件。
Redis 为每个 IO 多路复用函数库都实现了相同的 API,所以 IO 多路复用程序的底层实现是可以互换的。如图:
派大星:因此Redis 把所有连接与读写事件、还有提到的时间事件一起集中管理,并对底层 IO 多路复用机制进行了封装,最终实现了单进程能够处理多个连接以及读写事件。这就是 IO 多路复用在 redis 中的应用。
面试官:Redis 有哪些性能优化好的地方?
派大星:首先Redis是一个偏向 计算向数据移动、基于内存的、丰富的数据类型等等。
面试官:回答的不错
派大星:谢谢,如果对Redis的IO多路复用模型、以及Redis服务器处理的事件感兴趣,后续我可以出一片单独的文章进行讲解哈。
如有问题,欢迎加微信交流:w714771310,或关注微信公众号【码上遇见你】。