2.2 单线程架构
Redis内部使用单线程架构。Redis一个瞬间只能执行一条命令,不能执行两条命令
Redis单线程速度这么快的原因可大致归结三个:
- 纯内存
Redis把所有的数据都保存在内存中,而内存的响应速度是非常快的
- 非阻塞IO
Redis使用epoll异步非阻塞模型 ,Redis自身实现了事件处理
- 避免线程切换和竞态消耗
Redis使用epoll异步非阻塞模型 ,Redis自身实现了事件处理
主要原因是纯内存。
不过第二条和第三条倒是面试中经常会问到,尤其是第二条。为了便于大家,理解更深刻,我们这里探讨一下操作系统的IO
。
用户程序进行IO的读写,依赖于底层的IO读写,基本上会用到底层的read&write两大系统调用。
read系统调用,并不是直接从物理设备把数据读取到内存中;write系统调用,也不是直接把数据写入到物理设备。上层应用无论是调用操作系统的read,还是调用操作系统的write,都会涉及缓冲区。具体来说,调用操作系统的read,是把数据从内核缓冲区复制到进程缓冲区;而write系统调用,是把数据从进程缓冲区
复制到内核缓冲区
。
缓冲区的目的,是为了减少频繁地与设备之间的物理交换。外部设备的直接读写,涉及操作系统的中断。发生系统中断时,需要保存之前的进程数据和状态等信息,而结束中断之后,还需要恢复之前的进程数据和状态等信息。为了减少这种底层系统的时间损耗、性能损耗,于是出现了内存缓冲区。
有了内存缓冲区,上层应用使用read系统调用时,仅仅把数据从内核缓冲区复制到上层应用的缓冲区(进程缓冲区);上层应用使用write系统调用时,仅仅把数据从进程缓冲区复制到内核缓冲区中。底层操作会对内核缓冲区进行监控,等待缓冲区达到一定数量的时候,再进行IO设备的中断处理,集中执行物理设备的实际IO操作,这种机制提升了系统的性能。至于什么时候中断(读中断、写中断),由操作系统的内核来决定,用户程序则不需要关心。
从数量上来说,在Linux系统中,操作系统内核只有一个内核缓冲区。而每个用户程序(进程),有自己独立的缓冲区,叫作进程缓冲区。所以,用户程序的IO读写程序,在大多数情况下,并没有进行实际的IO操作,而是在进程缓冲区和内核缓冲区之间直接进行数据的交换。
有了对操作系统IO的基本认识之后,还要提一下操作系统四种主要的IO模型
- 同步阻塞IO(Blocking IO)
- 同步非阻塞IO(Non-blocking IO)
- IO多路复用(IO Multiplexing)
- 异步IO(Asynchronous IO)
Redis的IO模型是IO多路复用,有意思的是Java的NIO模型,也是IO多路复用(不是同步非阻塞IO)
有兴趣的可以查阅相关的资料,或者不着急的可以等我接下来的博文(过段日子会有网络编程详解的博文,对IO作深入探究)
这里还要强调一下,由于Redis单线程一次只运行一条命令,我们要拒绝长(慢)命令
keys flushall flushdb slow lua script mutil/exec operate