Redis 线程模型
Redis 的单线程是指对命令的执行是单线程,而 Redis 程序并不是单线程的:
- Redis 在 2.6 版本:会启动 2 个后台线程,分别处理关闭文件、AOF 刷盘这两个任务。
- Redis 在 4.0 版本之后:新增了一个新的后台线程,用来异步释放 Redis 内存,也就是 lazyfree 线程。因此,当我们要删除一个大 key 的时候,不要使用 del 命令删除,因为 del 是在主线程处理的,这样会导致 Redis 主线程卡顿,因此我们应该使用 unlink 命令来异步删除大key。
Redis 单线程为什么还这么快
- edis 的大部分操作都在内存中完成,因此 Redis 瓶颈可能是机器的内存或者网络带宽,而并非 CPU,既然 CPU 不是瓶颈,那么自然就采用单线程的解决方案了。
- Redis 采用单线程模型可以避免了多线程之间的竞争,省去了多线程切换带来的时间和性能上的开销,而且也不会导致死锁问题。
- Redis 采用了 I/O 多路复用机制处理大量的客户端 Socket 请求,IO 多路复用机制是指一个线程处理多个 IO 流,即 select/epoll 机制。简单来说,在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听 Socket 和已连接 Socket。内核会一直监听这些 Socket 上的连接请求或数据请求。一旦有请求到达,就会交给 Redis 线程处理,这就实现了一个 Redis 线程处理多个 IO 流的效果。
Redis 6.0 之后为什么引入了多线程
随着网络硬件的性能提升,Redis 的性能瓶颈有时会出现在网络 I/O 的处理上。
为了提高网络 I/O 的并行度,Redis 6.0 对于网络 I/O 采用多线程来处理。但是对于命令的执行,Redis 仍然使用单线程来处理,不要误解 Redis 有多线程同时执行命令。
多线程执行机制如下:
- 主线程负责接收建立连接请求,获取 socket 放入全局等待读处理队列
- 主线程处理完读事件之后,通过 RR(Round Robin) 将这些连接分配给这些 IO 线程
- 主线程阻塞等待 IO 线程读取 socket 完毕
- 主线程通过单线程的方式执行请求命令,将结果写回缓冲区
- 主线程阻塞等待 IO 线程将数据回写 socket 完毕
- 解除绑定,清空等待队列