Redis网络/线程模型
2020-04-22 10:26:42 0 举报
Redis I/O处理原理
作者其他创作
大纲/内容
可读写的文件描述符号fd5
BIO
系统调用
原子性,串行化
client
内核(内核空间)
SystemCall
单线程执行命令
App
多线程 IO 的读(请求)和写(响应)在实现流程是一样的,只是执行读还是写操作的差异。同时这些 IO 线程在同一时刻全部是读或者写,不会部分读或部分写的情况,所以下面以读流程作为例子。分析过程中的代码只是为了辅助理解,所以只会覆盖核心逻辑而不是全部细节。如果想完全理解细节,建议看完之后再次看一次源码实现。加入多线程 IO 之后,整体的读流程如下:主线程负责接收建连请求,读事件到来(收到请求)则放到一个全局等待读处理队列主线程处理完读事件之后,通过 RR(Round Robin) 将这些连接分配给这些 IO 线程,然后主线程忙等待(spinlock 的效果)状态IO 线程将请求数据读取并解析完成(这里只是读数据和解析并不执行)主线程执行所有命令并清空整个请求等待读处理队列(执行部分串行)上面的这个过程是完全无锁的,因为在 IO 线程处理的时主线程会等待全部的 IO 线程完成,所以不会出现 data race 的场景。
计算
程序
read
网卡:通过硬中断,指示cpu操作新发生的事件
I/O的发展过程
Select模型-多路复用
1、多线程,就会导致较多的系统调用,clone操作,消耗资源,每个的内存栈1m。2、根本问题,各个线程是阻塞的
鼠标or键盘
程序执行与内核的关系
I/O threads让主线程去多核读写,工作线程去计算,保证了操作的原子性和串行化
1、指令集,指令集是有级别的,用户的空间的操作,不能执行内核空间的指令集。需要通过systemcall中间调用。2、软中断和硬中断
对每一个客户端都需要进行以上操作,从客户端读取命令和数据,计算数据,然后返回数据
epoll函数
硬中断
redis是单线程的,操作是串行化的。
NIO两个层级:1、应用层级,new IO2、内核层级
1
CPU
NIO
select
select(fds)
write
EPOLL
内核
存在的问题
1、strace -ff -o 日志文件路径 运行程序命令如:strace -ff -o ./out java xxx.class 这样java程序在过程中,对系统的调用过程日志,就会输入到out文件中2、如果在执行过程中,生成了很多线程,就会有out.线程id 对应的文件生成3、/proc/主线程id 文件夹下,会有该线程对应的信息fd: 文件描述符,0:标准输入,1:标准输出,2:错误输出,这三个任何程序都会有类似java的对象,linux中一切皆文件task:线程对应的文件,这和程序中当前存在的线程数对应
worker
1、减少系统调用,select函数,传入所有的文件描述符,内核会返回,有那些文件描述符发生了变化。2、系统调用这些发生变化的文件描述符3、调用变化:O(n)->m+1问题:虽然减少了系统调用,但是1、在内核内部,对所有的文件描述符进行轮询,造成一定的资源浪费2、每次要传入所有的文件描述符select返回的是文件描述符,程序自己发生读写,还是同步的。
2
硬件
server
多线程读
软中断
因为服务端都在阻塞的等待客户端的操作,要使用多客户端,就要开启多线程。主线程一直在接收链接,然后开启另外到线程去处理链接
多线程写
问题:C10K问题1、10000客户端,每循环内O(n)的系统调用。如果每次可用的链接很少,将会造成大量的资源浪费为解决大量的无用系统调用,采用select内核函数解决
NIO模型
3
返回m个有操作的链接
0 条评论
下一页