Redis 事件驱动与多路复用源码剖析

在这里插入图片描述

1. 前言

Redis 是 单线程 + I/O 多路复用 的典型代表。
它并不是多线程处理请求,而是依赖 事件驱动(event-driven)模型,在一个线程内高效管理海量连接。

核心组件:

  • ae.c:事件驱动框架,封装了事件循环(event loop)。
  • anet.c:网络封装层,简化 socket API,提供可靠网络通信。
  • I/O 多路复用:底层可使用 epoll(Linux)、kqueue(BSD)、select(通用)。

2. Redis 事件模型概览

2.1 两类事件

  • 文件事件(File Event):指网络套接字上的读写操作。
  • 时间事件(Time Event):定时器任务(如定期持久化、心跳、清理)。

2.2 事件循环

Redis 的事件循环大致流程:

while (server is running) {# 处理文件事件(网络 I/O)aeProcessEvents(loop);# 处理定时事件processTimeEvents();# 执行后台任务(AOF 重写、内存释放)cron();
}

👉 事件循环是 Redis 单线程并发调度的核心


3. ae.c — 事件驱动框架

3.1 aeEventLoop 结构

ae.c 中,事件循环的核心结构是:

typedef struct aeEventLoop {int maxfd;                 // 当前已注册的最大 fdfd_set rfds, wfds;         // 监听的读写事件aeFileEvent *events;       // 已注册的文件事件aeFiredEvent *fired;       // 已触发的文件事件aeTimeEvent *timeEventHead;// 时间事件链表int stop;                  // 是否停止循环
} aeEventLoop;
  • events[]:保存所有已注册的 socket 事件。
  • fired[]:保存已触发的事件,等待回调执行。
  • timeEventHead:链表存放定时器任务。

3.2 注册文件事件

当一个客户端连接进来时,Redis 会调用 aeCreateFileEvent() 注册事件:

int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,aeFileProc *proc, void *clientData) {aeFileEvent *fe = &eventLoop->events[fd];fe->mask |= mask;      // 注册读/写事件fe->rfileProc = proc;  // 设置事件处理回调
}

👉 每个 socket fd 都绑定了 读写事件回调函数

3.3 事件分发与处理

事件循环执行时,会调用 aeProcessEvents()

int aeProcessEvents(aeEventLoop *eventLoop) {int numevents = aeApiPoll(eventLoop, ...); // 调用 epoll/select 等等待事件for (int j = 0; j < numevents; j++) {int fd = eventLoop->fired[j].fd;int mask = eventLoop->fired[j].mask;aeFileEvent *fe = &eventLoop->events[fd];if (mask & AE_READABLE) fe->rfileProc(fd, fe->clientData);if (mask & AE_WRITABLE) fe->wfileProc(fd, fe->clientData);}
}

👉 核心逻辑:等待事件 → 找到回调 → 执行回调


4. anet.c — 网络通信层

anet.c 对 BSD socket API 做了封装,简化了网络调用。

4.1 建立连接

int anetTcpServer(char *err, int port, char *bindaddr) {int s = socket(AF_INET, SOCK_STREAM, 0);anetSetReuseAddr(s);   // 设置 SO_REUSEADDRbind(s, ...);listen(s, 511);        // backlog = 511return s;
}

👉 创建 TCP 服务器 socket,并监听端口。

4.2 接收新连接

int cfd = accept(s, ...);
anetNonBlock(cfd);   // 设置非阻塞
anetEnableTcpNoDelay(cfd);

👉 新连接的 socket 设置为 非阻塞模式,避免 I/O 阻塞。


5. I/O 多路复用实现

Redis 在 ae_epoll.c / ae_kqueue.c / ae_select.c 中封装了多路复用实现。

5.1 epoll 示例

static int aeApiPoll(aeEventLoop *eventLoop, ...) {int numevents = epoll_wait(epfd, events, ...);for (int j = 0; j < numevents; j++) {eventLoop->fired[j].fd = events[j].data.fd;eventLoop->fired[j].mask = events[j].events;}return numevents;
}

👉 Linux 上默认使用 epoll,可支持 百万连接

5.2 select 回退

如果系统不支持 epoll/kqueue,Redis 会回退到 select 实现,保证兼容性。


6. 源码调用链梳理

完整链路如下:

server.c (主循环)└─ aeMain()└─ aeProcessEvents()└─ aeApiPoll()   # 调用 epoll_wait└─ rfileProc()   # 读事件回调,读取客户端命令└─ wfileProc()   # 写事件回调,返回响应

7. 单线程高并发的秘密

  1. 非阻塞 I/O:所有 socket 设置非阻塞。
  2. I/O 多路复用:同时监听大量 socket。
  3. 事件回调机制:读写操作通过回调函数执行,不会阻塞主线程。
  4. 计算与 I/O 解耦:命令解析、执行、响应都在主线程完成,避免线程切换开销。

👉 因此,Redis 在单线程下也能支撑 十万级并发请求


8. 小结

本文解析了 Redis 事件驱动与多路复用的实现:

  • ae.c:事件循环框架,统一调度文件事件和时间事件。
  • anet.c:封装 socket API,提供简化的网络接口。
  • I/O 多路复用:基于 epoll/kqueue/select,支持高并发连接。
  • 单线程模型:通过事件驱动和非阻塞 I/O,避免多线程锁竞争。

📌 Redis 高性能的核心秘诀之一,就是 单线程 + 多路复用 的高效事件驱动架构。


👉 下一篇我们可以写 Redis 命令执行流程与内核数据结构(命令表、解析、执行、回复机制),这样整个 Redis 执行链路就完整了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/923536.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/923536.shtml
英文地址,请注明出处:http://en.pswp.cn/news/923536.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VR煤矿实训系统相较于传统煤矿培训方式的独特优势​-广州华锐互动

高度逼真&#xff0c;沉浸体验​VR煤矿实训系统运用先进的3D建模、动态仿真技术&#xff0c;对煤矿井下的复杂环境进行1:1还原。从幽深的巷道、运转的采煤设备&#xff0c;到潮湿的空气、昏暗的灯光&#xff0c;甚至细微的煤尘颗粒&#xff0c;都能逼真呈现。使用者戴上VR设备后…

javaweb XML DOM4J

XMLXML作用就是配置文件&#xff0c;properties使用不了较复杂的需求&#xff0c;xml应运而生配置文件对比 xml更方便tips1:新建resources目录&#xff0c;并将src中的jdbc.properties移到resourcs中&#xff0c;并且右键标记为源代码根目录&#xff0c;这样运行src时就会和pro…

多模态视频理解领域 Benchmark 与 Leaderboard 整理

多模态视频理解是当前人工智能领域的研究热点&#xff0c;其核心目标是让模型像人类一样&#xff0c;综合视频中的视觉、听觉&#xff08;部分场景&#xff09;及文本信息&#xff0c;实现对视频内容的深度感知、理解与推理。为客观评估模型性能&#xff0c;行业内涌现了众多权…

18j621-3通风天窗图集pdf(免费高清版)

18j621-3通风天窗已经替代05j621-3通风天窗图集成为目前比较通用的建筑屋顶通风选型重要参考标准&#xff0c;18j621-3图集是对前图集的优化和革新&#xff0c;在18j621-3图集中新增了TC8圆拱型电动采光天窗&#xff0c;丰富了屋面通风排烟设备的选型。在18j621-3天窗图集中&am…

LawGPT:基于中文法律知识的大模型

本文转载自&#xff1a;https://www.hello123.com/lawgpt ** 一、⚖️ LawGPT&#xff1a;中文法律界的 “AI 法助”&#xff0c;啃透了 15 万份判决书&#xff01; LawGPT 是一系列专攻中文法律知识的开源大模型&#xff0c;在通用中文基座&#xff08;如 ChatGLM&#xff0…

用 go-commons 快速写一个监控 CPU/内存的 Exporter

欢迎加入开源项目&#xff0c;提你的 mr Go Commons&#xff1a;Golang 开发者的常用工具集&#xff0c;一站式解决常见需求 在 Go 语言的开发过程中&#xff0c;你是不是经常遇到这样的情况&#xff1a; 想要做点小功能&#xff0c;却得从零写起&#xff0c;或者到处找三方…

KingbaseES客户端工具Ksql使用全指南:从安装到高级操作

引言 在国产数据库蓬勃发展的今天&#xff0c;KingbaseES凭借其自主可控、高性能、高可用的特性&#xff0c;已成为政务、金融、能源等关键领域的首选数据库。而作为其配套的命令行工具&#xff0c;Ksql更是DBA和开发人员的“瑞士军刀”——它不仅能高效执行SQL查询&#xff0c…

【LeetCode - 每日1题】可以输入的最大单词数

🌈 个人主页:(时光煮雨) 🔥 高质量专栏:vulnhub靶机渗透测试 👈 希望得到您的订阅和支持~ 💡 创作高质量博文(平均质量分95+),分享更多关于网络安全、Python领域的优质内容!(希望得到您的关注~) 🌵目录🌵 难度 ⭐⭐ 题目回顾 ✅解题思路 💖概述 💓核心…

3227. 字符串元音游戏

3227. 字符串元音游戏 题目链接&#xff1a;3227. 字符串元音游戏 代码如下&#xff1a; class Solution { public:bool doesAliceWin(string s) {return ranges::any_of(s, [](char c) {return c a || c e || c i || c o || c u;});} };

微信小程序坐标位置使用整理(四)map组件

一、地图上标点&#xff0c;marker 1.wxml <map id"map" scale"9" class"map"markers"{{markers}}" longitude"{{longitude}}" latitude"{{latitude}}" show-location"{{true}}"><cover-vie…

Parlant框架深度技术解析:革命性AI代理行为建模引擎

引言 在人工智能快速发展的今天&#xff0c;AI代理&#xff08;Agent&#xff09;技术已经成为连接人工智能与实际应用场景的重要桥梁。然而&#xff0c;传统的AI代理开发面临着诸多挑战&#xff1a;提示词工程的复杂性、行为不可预测性、工具调用的不确定性等问题严重制约了AI…

AI重构车载测试:从人工到智能的跨越

目录 一、AI 在车载测试中的核心价值 二、AI 在车载测试的具体应用场景 (一)自动驾驶测试:AI 解决 “场景覆盖” 与 “决策可靠性” 难题 (二)车机系统测试:AI 优化 “交互体验” 与 “功能稳定性” (三)车载硬件测试:AI 实现 “故障预测” 与 “精准校准” (四)功能…

从职责划分看架构:MVC 的 Controller 与 MVVM 的 ViewModel 差异

深入浅出&#xff1a;前端MVC与MVVM架构模式&#xff0c;你真的懂了吗&#xff1f;✨ 序言 各位前端的“程序猿”和“程序媛”们&#xff0c;大家好&#xff01;&#x1f44b; 在前端开发的江湖中&#xff0c;MVC和MVVM这两个词&#xff0c;就像武林秘籍一样&#xff0c;常常被…

Vue-color:Vue.js 专业颜色选择器组件库 – 支持Vue2/3,TypeScript,暗色主题

简介 Vue-color 是一个专为 Vue.js 设计的颜色选择器组件库&#xff0c;提供了多种风格的颜色选择器组件。它支持 Vue 2.7 和 Vue 3&#xff0c;具有 TypeScript 支持、SSR 兼容性和暗色主题支持。 特性 多种颜色选择器 – 提供 Chrome、Sketch、Photoshop 等多种风格Vue 2.…

ArcGIS定向影像(2)——非传统影像轻量级解决方案

ArcGIS能让用户自己低成本的做出谷歌街景吗&#xff1f;现在ArcGIS Pro 3.2 和 ArcGIS Enterprise 11.2 能够让用户不使用任何插件和扩展的情况下完成街景数据集的构建&#xff0c;数据管理&#xff0c;发布服务和调用的完整解决方案。非常体系化&#xff0c;由底层数据驱动&am…

CKA05--service

Task 重新配置 spline-reticulator namespace 中现有的 front-end Deployment&#xff0c;以公开现有容器 nginx 的端口 80/tcp 创建一个名为 front-end-svc 的新 Service &#xff0c;以公开容器端口 80/tcp 配置新的 Service &#xff0c;以通过 NodePort 公开各个 Pod 解析&…

用 Go 采集服务器资源指标:从原理到实践

在后端开发或运维工作中&#xff0c;采集服务器资源指标 是个绕不开的需求&#xff1a; 运维要看 CPU、内存、磁盘的使用情况监控系统要定期上报这些数据应用程序有时候也需要根据系统负载做限流、弹性伸缩 那么问题来了&#xff1a;用 Go 怎么优雅地采集这些指标呢&#xff…

安卓学习 之 上下文菜单的操作

先来认识一下上下文菜单是什么样子的&#xff1f;如图&#xff0c;当长按一个控件时弹出来的菜单叫做上下文菜单&#xff1a;图中第一个和第二个就是一个上下文菜单&#xff0c;第二个菜单里面还有一层菜单&#xff0c;这个上下文菜单被绑定到注册按钮中&#xff0c;也就是长按…

fabric启动节点var/hyperledger/production: permission denied

场景我在节点的compose文件中进行了数据挂载&#xff1a;- ../../data/bank1/peer1:/tmp/hyperledger/bank1/peer1但是运行是依然报错为var/hyperledger/production的权限问题&#xff0c;并且我也已经对../../data/bank1/peer1目录设置了操作权限services:peer1-bank1:contain…

uni-app + Vue3 开发展示 echarts 图表

场景:使用 uni-app 开发手机端,需要展示 echarts 图表 1. 打开 uni-app 官网 https://uniapp.dcloud.net.cn/ 2. 点击右上角搜索 3. 点击插件市场,搜索 echarts 找到 echarts 插件 4. 下载到自己的项目中 使用详情在该页面下方.