pull/1/head
595208882@qq.com 4 years ago
parent c17ea16a9f
commit 9788cb53ed

@ -119,6 +119,8 @@ org.springframework.boot.env.YamlPropertySourceLoader
## 线程模型 ## 线程模型
![Redis线程模型](images/Middleware/Redis线程模型.png)
Redis内部使用文件事件处理器`File Event Handler`这个文件事件处理器是单线程的所以Redis才叫做单线程的模型。它采用`I/O`多路复用机制同时监听多个`Socket`,将产生事件的`Socket`压入到内存队列中,事件分派器根据`Socket`上的事件类型来选择对应的事件处理器来进行处理。文件事件处理器包含5个部分 Redis内部使用文件事件处理器`File Event Handler`这个文件事件处理器是单线程的所以Redis才叫做单线程的模型。它采用`I/O`多路复用机制同时监听多个`Socket`,将产生事件的`Socket`压入到内存队列中,事件分派器根据`Socket`上的事件类型来选择对应的事件处理器来进行处理。文件事件处理器包含5个部分
- **多个Socket** - **多个Socket**
@ -127,6 +129,12 @@ Redis内部使用文件事件处理器`File Event Handler`,这个文件事件
- **文件事件分派器** - **文件事件分派器**
- **事件处理器**(连接应答处理器、命令请求处理器、命令回复处理器) - **事件处理器**(连接应答处理器、命令请求处理器、命令回复处理器)
![Redis文件事件处理器](images/Middleware/Redis文件事件处理器.png)
### 通信流程
客户端与redis的一次通信过程 客户端与redis的一次通信过程
![Redis请求过程](images/Middleware/Redis请求过程.png) ![Redis请求过程](images/Middleware/Redis请求过程.png)
@ -149,7 +157,68 @@ Redis内部使用文件事件处理器`File Event Handler`,这个文件事件
### 效率高 ### 文件事件处理器
- **基于 Reactor 模式开发了自己的网络事件处理器文件事件处理器file event handler**
- 文件事件处理器 **使用 I/O 多路复用multiplexing程序来同时监听多个套接字**,并根据套接字目前执行的任务来为套接字关联不同的事件处理器
- 当被监听的套接字准备好执行连接应答accept、读取read、写入write、关闭close等操作时 与操作相对应的文件事件就会产生, 这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件
- 文件事件处理器以单线程方式运行, 但通过使用 I/O 多路复用程序来监听多个套接字, 文件事件处理器既实现了高性能的网络通信模型, 又可以很好地与 redis 服务器中其他同样以单线程方式运行的模块进行对接, 这保持了 Redis 内部单线程设计的简单性
### I/O多路复用
I/O多路复用的I/O是指网络I/O多路指多个TCP连接(即socket或者channel复用指复用一个或几个线程。意思说一个或一组线程处理多个TCP连接。最大优势是减少系统开销小不必创建过多的进程/线程,也不必维护这些进程/线程。
I/O多路复用使用两个系统调用(select/poll/epoll和recvfrom)blocking I/O只调用了recvfromselect/poll/epoll 核心是可以同时处理多个connection而不是更快所以连接数不高的话性能不一定比多线程+阻塞I/O好,多路复用模型中每一个socket设置为non-blocking,阻塞是被select这个函数block而不是被socket阻塞的。
**select机制**
**基本原理**
客户端操作服务器时就会产生这三种文件描述符(简称fd)writefds(写)、readfds(读)、和exceptfds(异常)。select会阻塞住监视3类文件描述符等有数据、可读、可写、出异常 或超时、就会返回返回后通过遍历fdset整个数组来找到就绪的描述符fd然后进行对应的I/O操作。
**优点**
- 几乎在所有的平台上支持,跨平台支持性好
**缺点**
- 由于是采用轮询方式全盘扫描会随着文件描述符FD数量增多而性能下降
- 每次调用 select(),需要把 fd 集合从用户态拷贝到内核态,并进行遍历(消息传递都是从内核到用户空间)
- 默认单个进程打开的FD有限制是1024个可修改宏定义但是效率仍然慢。
**poll机制**
基本原理与select一致也是轮询+遍历唯一的区别就是poll没有最大文件描述符限制使用链表的方式存储fd
**epoll机制**
**基本原理**
没有fd个数限制用户态拷贝到内核态只需要一次使用时间通知机制来触发。通过epoll_ctl注册fd一旦fd就绪就会通过callback回调机制来激活对应fd进行相关的io操作。epoll之所以高性能是得益于它的三个函数
- `epoll_create()`系统启动时在Linux内核里面申请一个B+树结构文件系统返回epoll对象也是一个fd
- `epoll_ctl()`每新建一个连接都通过该函数操作epoll对象在这个对象里面修改添加删除对应的链接fd, 绑定一个callback函数
- `epoll_wait()`轮训所有的callback集合并完成对应的IO操作
**优点**
- 没fd这个限制所支持的FD上限是操作系统的最大文件句柄数1G内存大概支持10万个句柄
- 效率提高使用回调通知而不是轮询的方式不会随着FD数目的增加效率下降
- 内核和用户空间mmap同一块内存实现(mmap是一种内存映射文件方法即将一个文件或其它对象映射到进程的地址空间)
例子100万个连接里面有1万个连接是活跃我们可以对比 select、poll、epoll 的性能表现:
- `select`不修改宏定义默认是1024则需要100w/1024=977个进程才可以支持 100万连接会使得CPU性能特别的差
- `poll` 没有最大文件描述符限制100万个链接则需要100w个fd遍历都响应不过来了还有空间的拷贝消耗大量资源
- `epoll`: 请求进来时就创建fd并绑定一个callback主需要遍历1w个活跃连接的callback即可即高效又不用内存拷贝
### 执行效率高
**Redis是单线程模型为什么效率还这么高**
- `纯内存操作`数据存放在内存中内存的响应时间大约是100纳秒这是Redis每秒万亿级别访问的重要基础 - `纯内存操作`数据存放在内存中内存的响应时间大约是100纳秒这是Redis每秒万亿级别访问的重要基础
- `非阻塞的I/O多路复用机制`Redis采用epoll做为I/O多路复用技术的实现再加上Redis自身的事件处理模型将epoll中的连接读写关闭都转换为了时间不在I/O上浪费过多的时间 - `非阻塞的I/O多路复用机制`Redis采用epoll做为I/O多路复用技术的实现再加上Redis自身的事件处理模型将epoll中的连接读写关闭都转换为了时间不在I/O上浪费过多的时间

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Loading…
Cancel
Save