Redis是单线程还是多线程?是单进程还是单线程?..等等,这个是大厂经常被问到的话题,下面来全面详解@mikechen
本篇已收于mikechen《最全大厂Java面试题及答案合集》里面。
具体来说,Redis使用一个单独的线程处理绝大部分的任务,包括:网络请求、数据读写...等,但最新的版本已经包含多线程的功能。
首先,从单线程谈起:
Redis单线程处理数据的方式之所以高效,是因为它利用了:I/O多路复用机制,可以同时处理多个客户端的请求。
I/O多路复用机制(I/O Multiplexing):是指在一个线程中,同时监控多个I/O通道。
比如:网络连接、文件描述符。。。等,这种机制可以显著提高系统的性能,特别是在需要同时处理多个客户端请求的场景中。
在Redis中,I/O多路复用机制,使单线程也能够同时处理大量的客户端请求。
通过该机制,Redis能够高效地管理成千上万个并发连接,实现高性能的数据读写。
实现原理,如下图所示:
Redis利用操作系统,提供的多路复用系统调用(如:select、poll、epoll等),来监听多个客户端的网络套接字。
select
是最早的I/O多路复用机制,允许在一个线程中监视多个文件描述符。
它通过检查每个描述符的状态(可读、可写、异常等)来处理I/O操作。
select的缺点是当监控的文件描述符数目增加时,其性能会大幅下降,因为它需要每次都检查所有描述符的状态。
poll
poll的原理类似于select,但是它解决了select在文件描述符数量过多时的性能问题。
poll不使用固定的文件描述符数量,而是使用链表来存储需要监视的文件描述符,因此可以支持更多的描述符。
epoll
epoll是Linux系统中的I/O多路复用机制,是对select和poll的优化,与它们不同,epoll是基于事件驱动的。
epoll,使用一个内核空间的事件通知机制,效率更高,并且,epoll可以支持大量并发连接,而且不需要在每次调用时遍历所有文件描述符。
因此,在高并发场景中性能优异,Redis在Linux系统中优先选择epoll。
此外,Redis的绝大多数操作都是内存操作,结合I/O多路复用,最大程度上避免了I/O等待,从而实现了高性能的数据处理能力。
不过,Redis也在特殊情况下使用多线程,比如:持久化操作...等等。
Redis支持,将内存数据写入磁盘(RDB、和AOF),在一些耗时较长的持久化操作中,Redis会启用子进程进行。
而且,从Redis 6.0开始,它增加了多线程支持(用于处理网络请求的读写操作),但数据处理仍然在单线程中完成,因此总体架构仍保持单线程特性。
本篇已收于mikechen《最全大厂Java面试题及答案合集》里面。