Skip to content

Commit 600225c

Browse files
authored
Create 3_Redis单线程模型.md
1 parent f437e19 commit 600225c

1 file changed

Lines changed: 83 additions & 0 deletions

File tree

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Redis 单线程模型
2+
3+
## Redis 单线程模型
4+
5+
Redis 基于 Reactor 模式开发了自己的网络事件处理器,这个处理器被称为文件事件处理器(file event handler)。由于文件事件处理器(file event handler)是单线程方式运行的,所以说 Redis 是单线程模型。
6+
7+
虽然 Redis 是单线程的,但仍然可以监听大量的客户端连接,原因在于文件事件处理器使用 **I/O 多路复用(multiplexing)程序**来同时监听多个客户端连接(即多个套接字),并根据套接字目前执行的任务来为套接字关联不同的事件处理器。也就是说,**I/O 多路复用技术使得 Redis 不需要额外创建多余的线程来监听客户端的大量连接,降低了资源的消耗**
8+
9+
### I/O 多路复用
10+
11+
多路指的是多个 Socke t连接,复用指的是复用一个线程。
12+
13+
多路复用主要有三种技术:select,poll,epoll。epoll 是最新的也是目前最好的多路复用技术。
14+
15+
16+
17+
### 文件事件处理器
18+
19+
Redis 服务器是一个事件驱动程序。服务器需要处理两类事件:
20+
21+
- 文件事件:服务器通过套接字与客户端或者其它服务器进行通信,**文件事件就是对套接字操作的抽象**
22+
- 时间事件:服务器有一些操作需要在给定的时间点执行,时间事件是对这类定时操作的抽象。
23+
24+
文件事件处理器主要是包含 4 个部分:
25+
26+
- 多个 Socket(客户端连接)
27+
- IO 多路复用程序(支持多个客户端连接)
28+
- 文件事件分派器(将 Socket 关联到相应的事件处理器)
29+
- 事件处理器(比如命令请求处理器、命令回复处理器、连接应答处理器)
30+
31+
Redis 选择使用单线程模型处理来自客户端的绝大多数网络请求,主要有以下 3 个原因:
32+
33+
- 几乎不存在 CPU 成为瓶颈的情况, Redis 主要受限于内存和网络。
34+
35+
Redis 并不是 CPU 密集型的服务,如果不开启 AOF 备份,所有 Redis 的操作都会在内存中完成不会涉及任何的 I/O 操作,这些**数据的读写由于只发生在内存中**,所以处理速度是非常快的;
36+
37+
整个服务的瓶颈在于**网络传输带来的延迟****等待客户端的数据传输**,也就是网络 I/O,所以使用多线程模型处理全部的外部请求可能不是一个好的方案。
38+
39+
- 使用单线程模型能带来更好的可维护性,方便开发和调试
40+
41+
单线程不需要并发控制。
42+
43+
- 使用单线程模型也能并发的处理客户端的请求
44+
45+
I/O 多路复用机制。
46+
47+
48+
49+
## Redis 4.0 后引入多线程
50+
51+
在 Redis 4.0 之后的版本,Redis 服务在执行一些命令时就会使用 ”主处理线程“ 之外的其他线程,例如 `UNLINK``FLUSHALL ASYNC``FLUSHDB ASYNC` 等非阻塞的删除操作。
52+
53+
对于 Redis 中的一些超大键值对,几十 MB 或者几百 MB 的数据并不能在几毫秒的时间内处理完,Redis 可能会需要在释放内存空间上消耗较多的时间。其实释放内存空间的工作可以由后台线程异步进行处理,只需要将键从元数据中删除,而真正的删除操作会在后台异步执行。Redis 引入多线程后,对于一些**大键值对的删除操作**,可以通过**多线程非阻塞地释放内存空间**减少对 Redis 主线程阻塞的时间,提高执行的效率。
54+
55+
总的来说,Redis 6.0 之前主要还是单线程处理。
56+
57+
58+
59+
## Redis 6.0 引入多线程
60+
61+
Redis6.0 引入多线程主要是为了提高网络 IO 读写性能。
62+
63+
虽然 Redis6.0 引入了多线程,但是 Redis 的多线程只是在**网络数据的读写这类耗时操作上使用**,执行命令仍然是单线程顺序执行。所以仍然是线程安全的。
64+
65+
Redis 6.0 的多线程默认是禁用的,只使用主线程。如需开启需要修改 redis.conf 配置文件:
66+
67+
```html
68+
io-threads-do-reads yes # 开启多线程
69+
```
70+
71+
开启多线程后,还需要设置线程数,否则是不生效的。同样需要修改 redis.conf 配置文件:
72+
73+
```html
74+
io-threads 2 # 官网建议 4 核的机器建议设置为2或3个线程,8 核的建议设置为6个线程
75+
```
76+
77+
关于线程数,官方有一个建议:4 核的机器建议设置为 2 或 3 个线程,8 核的建议设置为 6个线程,线程数一定要小于机器核数。
78+
79+
### Redis 6.0 多线程的实现机制
80+
81+
82+
83+
### Redis 6.0 多线程和 Memcached 多线程模型对比

0 commit comments

Comments
 (0)