Redis源码深挖带你走进技术最前沿,边学边懂底层秘密
- 问答
- 2026-01-19 21:43:46
- 3
主要参考自Redis官方GitHub仓库的源码文件,如src/server.h, src/t_string.c, src/db.c, src/dict.c, src/ziplist.c, src/ae.c等,以及Redis作者antirez和相关核心贡献者的博客与注释)
Redis源码深挖:带你走进技术最前沿,边学边懂底层秘密
想知道为什么Redis能这么快吗?光知道它用内存存储可不够,真正的秘密,都藏在它的源代码里,今天我们就当一回“代码侦探”,直接翻开Redis的“内脏”,看看它到底是怎么工作的。
第一站:钥匙和房间的奥秘——全局哈希表
当你执行SET username "zhangsan"时,这个键值对到底被放在哪里了?答案就在src/server.h文件里定义的一个超级重要的结构体,叫redisDb(也就是Redis数据库),你可以把它想象成一个大酒店,这个酒店里最核心的东西是一个巨大的“房间目录本”,官方名字叫dict,也就是字典或者哈希表。
这个“目录本”非常厉害,它把你的键(比如username)通过一个特殊的计算(哈希函数),直接转换成一个房间号码,这样,无论酒店(数据库)有多大,它都能用最快的速度(几乎是瞬间)找到username这个钥匙对应的是哪个房间,然后进去把值"zhangsan"放好,这个过程的时间复杂度是O(1),这就是Redis为什么读写得这么快的根本原因之一,源码文件src/dict.c详细实现了这个超级快的字典。
第二站:不只是简单的字符串——SDS的智慧

你可能觉得,Redis的字符串不就是C语言里的char*(字符数组)吗?大错特错!Redis自己发明了一种更聪明的字符串结构,叫SDS(Simple Dynamic String),定义在src/sds.h里。
SDS比C的原生字符串强在哪?主要有三招:
- 记性好:SDS的结构里有个字段专门记录字符串的长度,所以当你要查一个字符串多长时(用
STRLEN命令),Redis不用像C语言那样傻傻地从头数到尾直到看见结束符,它直接看一眼这个长度记录就行了,速度极快。 - 不怕撑:当你要修改字符串,比如用
APPEND命令追加内容时,SDS会自己检查空间够不够,如果不够,它会自动申请一块更大的内存,防止数据溢出导致程序崩溃。 - 省内存:SDS会根据字符串的实际长度,选择申请刚好的内存空间,不同长度的字符串用不同大小的结构头来管理,非常精细。
这就是为什么Redis处理字符串又安全又高效,SDS是幕后功臣。
第三站:小数据的大压缩——ziplist的匠心
Redis的List(列表)、Hash(哈希)等类型,在元素数量少、内容小时,并不会直接用链表或哈希表这种比较占内存的结构来存储,它们会使用一个叫ziplist(压缩列表)的东西,源码在src/ziplist.c。

ziplist就像是一个“紧凑的火车车厢”,它把所有的元素(比如一个Hash的字段和值)一个紧挨着一个地放在一块连续的内存里,这样做的好处是:
- 极致节省内存:因为它去掉了链表指针等额外的开销,对于海量的小数据存储,节省的内存是惊人的。
- 利用缓存:由于数据是连续的,更容易被CPU缓存命中,访问速度也更快。
当元素数量或大小超过一定限制时,Redis会自动把ziplist转换成标准的链表或哈希表,以保证在数据量变大时操作效率依然很高,这种“因地制宜”的设计思想,体现了Redis对性能和内存的极致追求。
第四站:单线程为什么快?——事件循环的真面目
这是最常被误解的一点,Redis确实是单线程处理命令的,但这不是它快的唯一原因,甚至不是最主要的原因,它的核心在于一个叫事件循环的机制,源码在src/ae.c(ae是Async Event的缩写)。
你可以把Redis的单线程想象成一个极其高效的“前台经理”,这个经理不会傻站着等某个客人(客户端)点单,他有一个神奇的本子(事件循环),上面记录着所有客人的需求:有的客人是刚来的要连接(可读事件),有的客人是点好单等着上菜(可写事件)。

这个经理的工作就是不停地翻看这个本子,看到哪个客人的需求准备好了,就立刻去处理一下,处理完一个,马上看下一个,因为所有操作都在内存中完成,所以每个命令的处理速度都极快(微秒级别),这样,即使同时服务成千上万个客人,这个经理也忙得过来,而且CPU始终处于高效运转状态,完全没有切换线程带来的开销。
更重要的是,这个单线程模型避免了复杂的锁问题,多线程编程中,为了防止数据被同时修改而出错,需要加锁,而锁的竞争和等待会严重拖慢速度,Redis的单线程从根本上杜绝了这个问题,保证了原子性,使得代码简单、稳定、高效。
第五站:持久化的魔法——RDB和AOF的底层实现
数据在内存里,断电不就没了吗?Redis通过持久化把数据存到磁盘上,主要有两种方式:
- RDB(快照):相当于给内存数据拍一张全景照片存起来,源码在
src/rdb.c,它通过fork出一个子进程来干这个体力活,子进程拥有和父进程一模一样的内存数据副本,然后由子进程安心地将数据写入磁盘,而父进程(主线程)继续快乐地处理命令,不受任何影响,这是典型的“写时复制”技术应用。 - AOF(日志):相当于记流水账,把每一个修改数据的命令都追加到一个文件里,源码在
src/aof.c,为了保证日志不丢失,Redis提供了多种刷盘策略(比如每秒刷一次),当AOF文件太大时,还会进行重写(BGREWRITEAOF),也是fork子进程来完成的,生成一个更紧凑的AOF文件。
通过阅读源码,你会发现持久化过程的设计充分考虑了不阻塞主线程和服务性能,这也是Redis稳健的基石。
挖完这一小部分源码,我们能看到Redis的快和稳不是偶然的:
- 用全局哈希表实现高速访问。
- 用SDS实现安全高效的字符串操作。
- 用ziplist等结构对小微数据进行极致的内存优化。
- 用单线程事件循环避免锁竞争,保证原子性和高吞吐。
- 用多进程协作(fork)实现持久化,不影响主服务。
这些精妙的设计都沉淀在一行行C代码中,阅读Redis源码,就像是在与顶尖的程序员对话,学习他们如何平衡性能、内存和稳定性,这不仅是学习一个数据库,更是学习系统编程的艺术,希望这次浅尝辄止的深挖,能让你有动力打开Redis的源码,去发现更多藏在深处的秘密。
本文由凤伟才于2026-01-19发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/83902.html
