文章目录:
[TOC]
本章从全局角度来看下redis服务设计的架构,从整体感官感受下redis 的各个数据结构、线程模型等之间的关联关系。希望整体的认识能给我们后续的redis 细分模块领域的学习做好铺垫。
我们可以带着问题去思考学习:
1.redis 的服务性能为什么处理的快?
2.reids 的服务性能为什么可以支撑高并发?
先看下整体的模块图:
redis 架构图.png
1. 顶层域划分:
首先大图分为三个域: 客户端、系统内核域、redis域。
我们需要描述清楚三者之间的关系,客户端是redisClient 发起的请求,属于跨进程的调用,redis域的 与客户端通信交互 需要 依赖
操作系统内核的 eventLoop 事件机制, 如此构成了整体的大模块的结构。
2. redis 模块划分:
模块 | 功能 |
---|---|
1.ae模块 | 负责网络事件 IO多路复用的 |
2.bio模块 | 负责后台job 执行 |
3.iothread多线程模块 | 负责并发读,并发写 |
4.zmalloc内存管理模块 | 负责内存管理 |
5.协议模块 | 负责客户端 和 服务端报文通信协议 |
6.DB模块 | 数据存储及命令执行模块 |
7.数据磁盘模块 | AOF、RDB |
8. ACL权限模块 | 访问控制权限 |
3. redis 启动流程:(main 线程)
- 执行启动命令: ./redis-server -选项
- 执行.initServerConfig 函数:
2.1 构造server单例,数据结构 server代表redis,里面包含了db,配置项等,所有和服务关联的数据。
2.2 挂载命令
2.3 初始化配置,从配置文件及命令中; - 执行 initServer 函数:
3.1 分配客户端列表
3.2 分配读写等待队列
3.3 db 内存分配
3.4 创建redis共享对象
3.5 createSocketAcceptHandler .aeCreateFileEvent 把新建接受链接的处理函数注册到 el 上;
3.6 设置 轮询中的 睡眠 前后 执行函数aeSetBeforeSleepProc(server.el,beforeSleep); - InitServerLast 服务最后的初始化动作;
4.1 bioInit(); /// backgroud 后台io 进程初始化
4.2 initThreadedIO(); // redis 引入的多线程 - loadDataFromDisk 从磁盘中加载redis 数据(AOF+RDB)
- mian.aeMain 事件循环函数,进入无限循环中执行函数 :aeProcessEvents
6.1 eventLoop->beforesleep 休眠前执行
6.1.1 执行并发读
6.1.2 执行命令执行
6.1.3 执行并发写
6.2 numevents = aeApiPoll(eventLoop, tvp); 如果没有事件,可能导致休眠,直到超时:
6.3 eventLoop->aftersleep(eventLoop); 休眠后执行函数:暂无耗时操作;
6.4 for 循环执行 events 事件; 事件执行 , 产生新的连接及读事件。
4. eventLoop 机制:
这个是实现我么你常说的IO多路复用的功能,网络事件(建立连接、收到数据、连接关闭) 会更新触发 eventLoop 产生对应的事件。 事件注册的时候,会把对应的回调处理函数hook 也写到 事件属性里面。
这样,在redis 域内,main 线程会不断轮询去取 eventList ,然后调用event 关联的proc,去处理回调。这里需要注意有哪些事件。
eventLoop的底层原理是 IO多路复用技术, 编译时会看执行的平台,选择不同平台的 多路复用函数。
参考: IO多路复用实现方式 select, poll ,epoll :
https://blog.csdn.net/fengyuyeguirenenen/article/details/124234675
5. 事件类型
- 文件事件->监听的端口的新链接事件;其中建立连接后,把连接的fd 会注册到 el上,当文件有读事件后,会触发 2.
- 文件事件->socket 有数据可读事件;
- 文件事件-> 连接关闭事件;
- 时间事件-> 轮询然后判断时间间隔,判断规则是否产生时间
6. redis 所有事件异步驱动逻辑点
- 网络事件: eventLoop 借助内核 实现网络事件的 异步及IO多路复用。
- 可读、可写客户端队列: 准备好的客户端都排在队列里面;
- 并发读写时间:读写队列执行前,main 线程会把任务分派给每个线程来执行;
- 时间事件: AOF 异步写等;
- 后台事件: 发送到对应类型job 的实践队列中;
实现的方式:数据结构分割数据,多线程根据数据及锁、标识写作。