Redis源码那些事儿,带你慢慢扒一扒它的秘密和结构
- 问答
- 2025-12-31 08:30:07
- 7
今天咱们就来聊聊Redis的源代码,用一种不那么技术宅的方式,看看这个速度飞快的“小东西”肚子里到底装了什么货,我们不追求大而全,就挑几个有意思的点,像看故事一样慢慢扒。
第一回:启动!从main函数开始漫游
想知道一个程序怎么跑起来的,最好的办法就是找到它的“出生点”——main函数,在Redis的源码里,这个入口藏在src/server.c这个文件里,你可别被这个普通的文件名骗了,它可是Redis的“大脑中枢”。
一进入main函数,你会发现它干的事情其实很有条理,就像一个经验丰富的管家在启动一座大宅子的各项功能,它要初始化服务器配置(来源自Redis源码server.c中的initServerConfig函数),这步就像是给服务器设定初始参数:默认监听哪个端口(6379)、默认有多少个数据库(16个)、各种数据结构的初始设置等等,这时候的配置还都是“出厂设置”。

一个关键的步骤来了,叫做负载命令行参数(来源自Redis源码server.c中对命令行参数的处理逻辑),我们启动Redis的时候,是不是可以加一堆参数,比如redis-server --port 6380?就是在这里,main函数会检查我们输入的命令,用我们自定义的配置覆盖掉刚才的“出厂设置”,这体现了Redis的灵活性,一切都可配置。
配置搞定后,就轮到初始化服务器(来源自Redis源码server.c中的initServer函数)这个大活儿了,这一步非常关键,它为我们即将运行的服务器搭建好了舞台,它具体干了啥呢?
- 创建事件循环(Event Loop):这是Redis高性能的“心脏”,Redis之所以能同时处理成千上万个客户端的连接,而不为每个连接创建一个昂贵的线程,全靠这个叫
aeEventLoop的东西(来源自Redis源码ae.c),你可以把它想象成一个超级高效的任务调度员,它一直盯着所有网络连接,哪个连接有数据来了,它就立刻通知Redis去处理,这避免了CPU在原地傻等,实现了惊人的并发能力。 - 初始化数据结构:Redis不是号称数据结构服务器吗?它那些宝贝的字典(Hash)、列表(List)、集合(Set)等等,它们的内存分配器、全局字典等都在这里进行初始化准备。
- 打开监听端口:也就是开始“开门迎客”了,服务器开始绑定我们设定的端口(比如6379),准备接受来自客户端的连接。
初始化完毕,main函数最后会启动事件循环(来源自Redis源码server.c中调用aeMain函数),一旦执行到这,Redis就正式进入了“工作状态”,那个事件调度员(Event Loop)开始永不停歇地轮询,处理网络请求,整个服务器就“活”了起来。
第二回:核心秘密之“快”从何来?内存与数据结构

大家都知道Redis快,是因为它把数据都放在内存里,但这只是故事的一半,内存操作固然快,但如果数据结构设计得不好,就像在一个杂乱无章的巨型仓库里找东西,依然快不起来,Redis的另一个“杀手锏”就是它精心设计的数据结构。
我们拿最常用的string(字符串)类型举个例子,在Redis里,一个字符串值可不是傻乎乎地只存在一种形式,它有一个聪明的机制,叫SDS (Simple Dynamic String)(来源自Redis源码sds.h和sds.c),SDS相比C语言原生的字符数组(char[]),有几个绝活:
- O(1)时间复杂度获取字符串长度:C语言要知道一个字符串多长,得从头到尾数一遍,直到遇到结束符'\0',这是O(n)的操作,而SDS在结构体里直接存了长度的值,读取长度瞬间完成。
- 杜绝缓冲区溢出:SDS在操作前会检查空间是否足够,不够就自动扩容,非常安全。
- 减少内存重分配:SDS采用了“预分配”和“惰性空间释放”的策略,比如你把一个SDS从"hello"追加成"hello world",它可能一次会多分配一些空间,下次你再追加短字符串时,就不用立刻再去申请内存了,这提升了效率。
你看,光是底层最基础的字符串实现,就有这么多优化心思,更别提那些复杂的哈希表、跳跃表了,Redis会根据数据量的大小和类型,自动选择最节省内存、访问效率最高的内部编码(比如用ziplist压缩列表还是hashtable哈希表来实现一个Hash键),这一切对用户都是透明的,这种对数据结构的极致打磨,是Redis在内存中也能飞起来的另一个核心原因。
第三回:持久化的“中庸之道”

数据都在内存里,一断电不就全没了吗?Redis当然考虑了这点,它提供了两种主要的持久化方式:RDB和AOF,这俩的设计理念很有意思,有点像“鱼与熊掌”的权衡,而Redis选择的是“我都要,但分场合”。
-
RDB(快照):就像是给数据库拍一张全景照片(来源自Redis源码rdb.c),在某个时间点,Redis会把内存里所有数据完整地序列化后压缩,保存成一个二进制的dump.rdb文件,这个方式的优点是文件紧凑,恢复大数据集时速度极快,缺点就是可能会丢数据,因为如果每隔5分钟拍一次快照,那么服务器故障时,最多可能丢失5分钟的数据,它是备份和灾难恢复的理想选择。
-
AOF(追加日志):则像是记日记(来源自Redis源码aof.c),它不记录数据本身,而是记录下所有会修改数据的写命令(比如SET, LPUSH等),每执行一个写命令,这个命令就会以协议格式追加到AOF文件的末尾,当Redis重启时,它会重新按顺序执行一遍AOF文件里的所有命令,从而还原内存状态,它的优点是数据安全性高,通常配置为每秒同步一次日志,最多丢一秒数据,缺点是文件体积会越来越大,而且恢复速度比RDB慢。
Redis的聪明之处在于,它允许你同时开启RDB和AOF,或者只开一种,甚至,它还提供了AOF重写机制(来源自Redis源码aof.c中的rewriteAppendOnlyFile函数),因为AOF文件是追加的,里面可能有很多重复或过时的操作(比如对一个键先set a 1,又set a 2,最后del a,那前两条命令其实就没用了),重写机制会fork一个子进程,根据当前数据库状态,逆向生成一个全新的、最精简的AOF命令序列,从而压缩日志文件大小,这种灵活、可配置的持久化策略,让用户可以根据业务在性能和数据安全之间找到最佳平衡点。
扒了这么三点,我们能看到Redis的成功绝非偶然,从清晰的程序结构,到高性能事件驱动模型,再到精心优化的数据结构和灵活的持久化方案,每一层设计都体现了开发者对效率和实用性的深刻理解,它的源码就像一个宝库,值得慢慢挖掘。
本文由帖慧艳于2025-12-31发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/71778.html
