type
Post
status
Published
date
Apr 27, 2024
slug
summary
tags
数据库
Redis
category
学习思考
password
icon
epoll
epoll 是 I/O 事件通知模型。epoll在监听事件的时候需要两个维护两个epoll_event记录集,1是用于需要监听的事件的 ,2是用于记录已就绪的监听事件。相关API
epoll_create : 创建 epoll 实例
epoll_wait : 等待就绪的描述符,timeout=0立即返回,timeout=1阻塞式等待。
epoll_ctl: 将描述符改增删操作,op
EPOLL_CTL_ADD, EPOLL_CTL_MOD, EPOLL_CTL_DEL。epoll 简单使用流程
Redis 的 Reactor 模型
Reactor 的介绍:Reactor 是一个异步的编程模型。
Redis 的 Reactor 封装相关代码在
ae.c ae.h,在启动服务时候会创建一个事件循环体,调用aeEventLoop *aeCreateEventLoop(int setsize)方法 setzise 为server.maxclients+CONFIG_FDSET_INCR 客户端最大连接数(默认10000)+ 额外配置(128)。初始化 Event Loop
监听事件并绑定回调函数
等待回调
Redis 监听客户端
在
server.c 中 main() 方法中初始化一系列操作后会调用 server.el = aeCreateEventLoop(server.maxclients+CONFIG_FDSET_INCR); 创建一个循环体,然后执行 initListeners()方法,initListeners 会根据用户配置的端口数量监听 fd,调用 createSocketAcceptHandler()方法将 listener 的 fd 与回调函数指针绑定,如果连接的是TCP/IP Socket 回调函数就是 connSocketAcceptHandler,如果是 Unix Socket 的话回调函数是 connUnixAcceptHandler,当监听到 listener 的 fd 可读,说明有客户端请求连接,就回调执行所对应的函数处理。创建好客户端连接后继续把 client 的 fd 添加到 epoll 监听,大致流程是这样connSocketAcceptHandler()→acceptCommonHandler()→createClient()→
connSetReadHandler(conn,readQueryFromClient)→aeCreateFileEvent(server.el,conn->fd,AE_READABLE,conn->type->ae_handler,conn)readQueryFromClient() 方法就是 client 的 fd 可读的就绪的回调处理函数,接下来Redis 会解析命令、查询数据库、并把结果响应回客户端。
总结
可以看到 Redis 封装的 Reactor 编程模型,事实上是在 epoll 的 api 基础上加上一些功能,比如 在
aeFileEvent 记录了相对应的 fd 要执行的函数指针,等待有就绪的fd就执行回调方法。 aeMain () 基本上是单个线程一直循环,有事件就去处理,eopll 可以返回多个 fd 的事件就绪状态而不用阻塞式的等待某个 fd 事件就绪,这让 Redis 使用单线程也可以处理很多请求连接。