epoll之redis自顶向下

Epoll 之 Redis 自行向下

Wirte by 021. Leave a message if i messed up ! : )

LINUX – IO MULTIPLEXING – SELECT VS POLL VS EPOLL | Byte_Liu's Blog

Redis系统架构- 知乎

IO 进化史

BIO阻塞IO

  • Socket阻塞伪代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

//有1000个客户端读文件描述符的需求
files waitRead = read(fd)*1000;

1, file = read(waitRead[0]);

2, if(file != null)
{
//do work
}


//单线程阻塞, 只能使用多线程处理, 每一条线程处理一个文件描述符的读取系统调用

new Thread(

files waitRead = read(fd)*1000;

1, file = read(waitRead[0]);

2, if(file != null)
{
//do work
}

).start();


NIO同步非阻塞

  • 同步非阻塞伪代码模拟**
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

//有1000个读文件描述符的需求
read(int fd) * 1000;

for(;;)
{

for(1000 * fd) // 用户空间 系统调用轮询1000次,
{
file = read(fd1~fd1000); //轮询读取每一个fd文件描述符,不管数据有没有准备好

if(file != null)
{
// do work....
}

}
}

Select(多路复用)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

//有1000个读文件描述符的需求
read(int fd) * 1000;

//select 系统调用函数, 一次性传输多个文件描述符传输给内核,返回准备好的文件描述;
select(fd*1000);



file fds = select(fd*1000); // 系统调用,内核返回准备好的文件的描述符
for( 0;fds; ) // 用户空间遍历内核返回的全部文件描述符,
{

if(fd.readAble) //检测文件可读状态
{

file = read(fd);
if(file != null)
{
// do work....
}

}
}




epoll
  • 模拟内核 和 用户 共享空间逻辑

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

    模拟原始内存空间:

    0xffffffff ------------用户空间-------------0x80000000 ------------内核空间------------ 0x00000000;


    模拟共享空间: //用户与内核 映射 同一块物理空间

    0xffffffff ---------用户空间---------[0x80000000 ---共享空间--- 0x700000000 ]------内核空间----- 0x00000000;


    // 共享空间容器
    1,红黑树 - 等待读取的文件描述符 ,btree;
    2,链表 - 准备好的文件描述符 , readyLinkList;


    btree.add(epoll.creat(fd)); // 将待读取的文件描述符 放入共享空间的红黑树.

    file = read(readyLinkList(fd)); //读取 共享空间 链表容器 已准备好的文件描述符;






redis 单进程 单线程 为什么快?

  • 如何保证顺序性?
    • 每个连接
  • sendfile 零拷贝