
文章目录
https://blog.csdn.net/qq_27706119/article/details/123431605
https://blog.csdn.net/D1179869625/article/details/125353803
https://blog.csdn.net/xmtblog/article/details/118533110
《Redis 设计与实现》 P167
1. 为啥说 Redis 是单线程的?
Redis 基于 Reactor 模式设计开发了自己的一套高效的事件处理模型,这套事件处理模型对应的是 Redis 中的文件事件处理器。由于文件事件处理器是单线程的方式运行的,所以我们一般来说 Redis 是单线程的。
这个单线程是指在处理网络请求的时候是单线程处理,但是一个正式的 Redis Server 运行时肯定不止一个线程,比如 Redis 进行持久化操作的时候会 fork 一个子进程。
2. Redis 的两类事件
Redis 服务器是一个事件驱动程序,服务器需要处理以下两类事件:
- 文件事件:Redis 服务器通过套接字与客户端(或其它 Redis 服务器)建立连接,而文件事件就是服务器对套接字操作的抽象。服务器与客户端(或其它服务器)的通信会产生相应的文件事件,而服务器则通过监听这些事件来完成一系列的网络通信操作。
- 时间事件:Redis 服务器中的一些操作(如 serverCron 函数)需要在给定的时间点执行,而时间事件就是服务器对这类定时操作的抽象。
3. 文件事件处理器
Redis 中的文件事件处理器由四部分组成,分别为套接字、I/O 多路复用程序、文件事件分派器和事件处理器。
文件事件是对套接字操作的抽象,每当一个套接字准备好执行连接、应答、写入、读取、关闭等操作时,就会产生相应的文件事件。
I/O 多路复用程序负责监听多个套接字,并向文件事件分派器传送那些产生了事件的套接字。尽管多个文件事件可能会并发出现,但 I/O 多路复用程序会将所有产生事件的套接字都放在一个队列中,然后通过这个队列,以有序、同步、每次一个套接字的方式向文件事件分派器传送套接字。当上一个套接字产生的事件被相应的事件处理器处理完毕后,I/O 多路复用程序才会继续向文件事件分派器传送下一个套接字。
文件事件分派器接收 I/O 多路复用程序传来的套接字,并根据套接字产生的事件类型,调用相应的事件处理器。服务器会为执行不同任务的套接字关联不同的事件处理器,这些处理器是一个个函数,它们定义了某个事件发生时,服务器应该执行的动作。
4. I/O 多路复用程序的实现
Redis 的 I/O 多路复用程序的所有功能都是通过包装常见的 selelct、epoll 和 kqueue 这些 I/O 多路复用函数库来实现的。因为 Redis 为每个 I/O 多路复用函数库都实现了相同的 API,所以 I/O 多路复用程序的底层实现是可以互换的。
Redis 在 I/O 多路复用程序的实现源码中使用 #include 宏定义了相应的规则,程序会在编译的时候自动选择系统中性能最高的 I/O 多路复用函数库来作为 Redis 的 I/O 多路复用程序的底层实现。

5. 时间事件


6. 为啥单线程的 Redis 还这么快?
- Redis 是基于内存来存取数据的,内存存取数据的速度远快于磁盘的存取速度;
- Redis 基于 Reactor 模式开发了自己的一套高效的事件处理模型,也就是文件事件处理器,并采用 I/O 多路复用模型来处理大量的网络请求;
- 单线程的方式处理网络请求,避免多线程时的上下文切换、加锁等操作的性能开销;
- 使用高效的底层结构,如哈希表、跳表等,能快速访问数据。
7. Redis 6.0 引入多线程
https://blog.csdn.net/ldw201510803006/article/details/124790121
我们经常听说 Redis 是单线程模型,其实仅仅指的是网络请求的处理是使用单线程的,但其实,还有一些由对应特殊的线程来完成。在 Redis 6.0 之前,完整的 Redis 线程模型是主线程(1个)+ 后台线程(3个):

三个后台线程分别处理:
- close_file:关闭 AOF、RDB 等过程中产生的大临时文件
- aof_fsync:将追加至 AOF 文件的数据刷盘(一般情况下 write 调用之后,数据被写入内核缓冲区,通过 fsync 调用才将内核缓冲的数据写入磁盘)
- lazy_free:惰性释放大对象
这三个线程有一个共同的特点,都是用来处理耗时较长的操作,也印证了我们常说的,专业的人做专业的事。通常情况下,Redis 性能瓶颈可能存在于网络和内存,而不是 CPU。针对网络,一般是处理请求速度较慢的问题;针对内存,一般是指物理空间的限制。
一般来说,处理一个 Redis 请求可以分为两部分,网络模块 + 命令处理模块。在网络模块中引入多线程来处理,这些线程也叫做 IO 线程,由于主线程也会处理网络模块的工作,因此主线程习惯上也叫做主 IO 线程。
网络模块有接收连接、IO 读写(包括数据解析)、IO 写等操作;其中主线程负责接收新连接,然后分发到 IO 线程进行处理(主线程也参与)。

虽然 Redis 6.0 引入了多线程,但是 Redis 的多线程只是在网络数据的读写这类耗时的操作上使用了,执行命令时仍是单线程顺序执行。因此,用户无需担心线程安全问题。
Redis 6.0 的多线程默认是禁用的,只使用主线程。如需开启,可以修改 Redis 的配置文件 redis.conf
io-threads-do-reads yes
开启多线程后,还需要设置线程数,否则无法生效。同样需要修改 Redis 配置文件 redis.conf
io-threads 4 #官网建议4核的机器建议设置为2或3个线程,8核的建议设置为6个线程
Redis是基于单线程的事件驱动程序,主要通过文件事件处理器处理网络请求,利用I/O多路复用技术高效处理多个套接字。文件事件处理器包括套接字、I/O多路复用程序、文件事件分派器和事件处理器四个部分。Redis6.0开始引入多线程来处理网络数据的读写,以提高性能,但命令执行仍保持单线程,以确保线程安全。
1731

被折叠的 条评论
为什么被折叠?



