redis服务器是一个由事件驱动(死循环)的程序,它总共就干两件事:
- 文件事件:利用I/O复用机制,监听Socket等文件描述符发生的事件,如网络请求
- 时间事件:定时触发的事件,负责完成redis内部定时任务,如生成RDB文件、清除过期事件
redis事件api
-
aeApiCreate:初始化I/O复用机制上下文环境
-
aeApiAddEvent、aeApiDelEvent:增加或删除一个监听对象
-
aeApiPoll:阻塞进程,等待事件就绪或给定事件到期
-
aeEventLoop:redis事件循环器,负责管理事件
-
aeFileEvent:存储一个文件描述符已注册的文件事件
-
aeTimeEvent:存储一个时间事件的信息
-
redis启动时创建的事件
- 初始化aeEventLoop属性
- aeApiCreate由I/O复用层实现,并初始化具体的I/O复用机制执行的上下文环境
-
监听TCP Socket,并指定函数处理
- 如果超出eventLoop.setsize限制,则返回错误
- aeApiAddEvent函数由I/O复用层实现,调用I/O复用函数添加监听事件对象
- 初始化aeFileEvent属性
-
redis定时任务
- 初始化aeTimeEvent属性,计算下一次时间事件执行事件
- 头插到eventLoop.timeEventHead链表
-
事件循环器的运行
- 阻塞进程,等待文件事件就绪或时间事件到达执行事件
- 按规则计算进程最大阻塞时间
- 查找最先执行的时间事件,若有,则用该时间减去当前时间
- 检查是否AE_DONT_WAIT标志,若无则一直阻塞,若有,则不阻塞,轮询系统是否有就绪事件
- 进程阻塞前,执行beforeSleep函数
- aeApiPoll负责阻塞进程,直到有文件事件就绪或时间到期
- 进程阻塞后,执行afterSleep函数
- aeApiPoll返回已就绪的文件事件数量并处理
- 通常redis会优先处理read事件再处理write事件,以方便服务器尽快处理请求返回结果给客户端。aeApiAddEvent如果设置了优先处理write属性,则会优先处理write事件。
- 处理时间事件
-
处理时间事件
- 判断上一次执行事件的时间是否比当前时间大?若是就说明系统时间有问题,则将所有时间事件过期时间置为0提前执行,提前执行危害小于延后执行.
- 遍历时间事件
- 若事件已删除,则将其从链表中删除
- 若时间事件已经到了执行时间,则删除
- 处理下一个时间事件