"单线程Redis为什么这么快?"
- Redis是一个基于内存的数据库,直接操作内存,存取类似于HashMap,O(1)
- Redis单线程&IO多路复用
为什么单线程?
-
之前在我的理解里,现今的服务器都是多核CPU,为什么不充分利用机器特性,引入多线程提高并发性能?
-
Redis选择使用单线程模型处理客户端的请求主要还是因为CPU不是Redis服务器的瓶颈,使用多线程模型带来的性能提升并不能抵消它带来的开发成本和维护成本,系统的性能瓶颈也主要在网络 I/O 操作上;
但是为什么又在Redis6.0之后的版本开始选择性使用多线程模型?
- 引入多线程操作也是出于性能上的考虑,对于一些大键值对的删除操作,通过多线程非阻塞地释放内存空间也能减少对 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中的应用。