Redis多线程单线程问题
# Redis多线程单线程问题
# 1 文件事件处理器
连接池中的连接数不等于线程池中的线程数,连接池就是一个list,里面存放socket,可以用一个或多个线程去管这个连接池。
Redis基于Reactor模式开发了自己的事件处理器:这个处理器被称为文件事件处理器。文件事件处理器使用 IO 多路复用程序来同时监听多个套接字,并根据套接字目前执行的任务来为套接字关联不同的事件处理器。
当被监听的套接字准备好执行连接应答、读取、写入、关闭等操作时,与操作相应对的文件事件就会产生,这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。
虽然文件事件处理器以单线程方式运行,但通过使用 IO 多路复用程序来监听多个套接字,文件事件处理器实现了高性能的网络通信模型,又可以很好地与 Redis 服务器中其他同样以单线程方式运行的模块进行对接,这保持了 Redis 内部单线程设计的简单性。
文件事件处理器主要包含4部分:
- 多个socket(客户端连接)
- IO多路复用程序(支持多个客户端连接的关键)
- 文件事件分派器(将socket关联到相应的事件处理器)
- 事件处理器(连接应答处理器、命令请求处理器、命令恢复处理器)
# 2 Redis 单线程模型
工作线程是单线程,IO 是多线程。
Redis 基于 Reactor 模式来设计开发了自己的一套高效的事件处理模型。这套事件处理模型对应的是 Redis 中的文件事件处理器(file event handler)。由于文件事件处理器是单线程方式允许的,所以我们一般都说 Redis 是单线程模型。
Redis 通过 IO 多路复用程序来监听来自客户端的大量连接,IO 多路复用技术的使用让 Redis 不需要额外创建多余的线程来监听客户端的大量连接,降低了资源的消耗。
Redis 服务器是一个事件驱动服务器,服务器需要处理两类事件:1. 文件事件;2. 事件事件。我们接触最多的是文件事件。
# 3 Redis没用使用多线程?为什么不使用多线程
虽然说 Redis 是单线程模型,但是 Redis 在 4.0 之后的版本就已经加入对多线程的支持。不过 4.0 增加的多线程主要是针对一些大键值对的删除操作的命令,使用这些命令就会使用主处理之外的其他程序来异步处理。
大体上,Redis6.0 之前还是单线程处理。因为:
- 单线程编程容易并且容易维护
- Redis 的性能瓶颈不在 CPU,主要在内存和网络
- 多线程会存在死锁、线程上下文切换等问题,甚至影响性能
# 4 Redis6.0后为何引入多线程
Redis6.0 引入多线程主要是为了提高网络 IO 读写性能,因为这个算是 Redis 的性能瓶颈(受限于内存和网络)。
虽然 Redis6.0 引入了多线程,但是 Redis 的多线程只是在网络数据的读写这类耗时操作上使用,执行命令仍然是单线程顺序执行。