又回到Redis源码里瞅瞅那些文件,想弄明白它到底咋开的
- 问答
- 2026-01-12 11:14:59
- 4
那天我又手痒,点开了Redis的源码文件夹,这次不是要改啥,就是想随便逛逛,看看这个天天用的家伙,它到底是怎么“活”过来的,换句话说,我想弄明白,从我在命令行里敲下redis-server那一刻起,到它乖乖地在那里监听6379端口,中间到底发生了啥,我不打算深究那些复杂的数据结构,就想跟着程序的脚步走一遍。
我首先找的是程序的“大门”,也就是main函数,这在src目录下的server.c文件里,很容易就找到了,这个文件老长了,一看就是核心中的核心。main函数一开头,并没急着干大事,而是先做了好多“家务活”,它定义了一大堆变量,然后调用了spt_init这样的函数,我瞅了瞅注释和代码,这好像是在为后面可能用到的进程守护(就是变成后台服务)啊、信号处理啊做准备,确保程序在各种环境下都能正确设置自己的身份和行为,这就像一个人出门前,先检查下钥匙钱包手机带没带,虽然琐碎,但很重要。
它开始读取命令行参数,这部分代码就是处理我们启动Redis时后面跟的那些--port 6380或者--daemonize yes之类的选项,它用一个循环挨个检查argv里的参数,然后设置对应的配置变量,如果看到--port,就知道下一个参数是端口号,把它记下来,这里我注意到,它并没有立刻应用这些配置,而是先存起来,好像是在等一个更合适的时机。

存完命令行参数,一个非常重要的函数出现了:initServerConfig,我跳进去看了看(这个函数也在server.c里),这里才是真正给服务器的各种设置赋初始值的地方,默认端口就是在这里被设为6379的,默认的数据库数量是16个,各种超时时间、日志级别等等,都在这儿被赋予了“出厂设置”,这让我明白了,Redis先把用户命令行给的配置记下,然后用默认配置打底,这样后面再合并的时候,用户设置的优先级更高。
又一个关键步骤:loadServerConfig,这个函数是去加载配置文件(redis.conf)的,它会把配置文件里的每一行解析出来,覆盖掉之前的默认值或者命令行参数,这里有个细节,命令行参数的优先级是最高的,因为它是最后被处理的,代码里会先调用loadServerConfig处理配置文件,但如果在配置文件里遇到某些选项,而命令行里又指定了同样的选项,那么命令行的设置会最终胜出,这个过程就像叠被子,先铺上默认的床单(initServerConfig),再盖上配置文件的被子(loadServerConfig),最后如果用户觉得冷,又加了个命令行的小毯子。

配置都加载完毕,服务器的“人格”基本上就确定了:它要监听哪个端口、是不是后台运行、日志怎么写等等。main函数里调用了initServer,这个函数可是个大工程,我花了点时间仔细看了看,它干了好多实事:
它创建了事件循环(event loop),Redis是单线程处理命令的,但能同时处理成千上万的网络连接,靠的就是这个叫aeEventLoop的东西。initServer里调用了aeCreateEventLoop来创建它,这相当于给Redis装上了心脏,之后所有网络连接的读写、定时任务的执行,都由这个事件循环来调度。

它开始监听网络端口,代码里调用了anetTcpServer等函数,创建了监听套接字(listening socket),这就像在服务器上安装了一个门铃,告诉操作系统:“我在这个端口上等着,有客户来敲门你就通知我。” 创建好监听套接字后,Redis又做了一个关键动作:它调用aeCreateFileEvent,把这个监听套接字注册到了刚才创建的事件循环里,并告诉事件循环:“你帮我盯着这个‘门铃’,一旦有新的连接进来(即变得可读),你就回调我的acceptTcpHandler函数。” 这样一来,事件循环就和网络监听关联起来了。
在initServer里,它还做了很多其他初始化工作,比如创建各个数据库、初始化各种统计变量、设置LRU时钟、创建后台IO线程(现代Redis版本支持的)的管道等等,感觉就像在布置一个家的内部,桌椅板凳(数据结构)摆好,各种工具(功能模块)准备齐全。
当initServer执行完,服务器本身已经“五脏俱全”了,但还差最后一步:让心脏跳动起来,回到main函数,在一切准备就绪后,有一行特别显眼的代码:aeMain(server.el),这个aeMain函数,接收的就是那个事件循环,它一被调用,就进入了一个无限的while循环,不断地检查有没有网络事件发生、有没有定时任务需要执行,程序执行流到了这里,就停住不走了,Redis服务器正式进入了事件驱动的工作模式,开始它永恒的等待和服务。
在进入aeMain之前,main函数还打印了那句熟悉的日志:“Ready to accept connections”,这就像一个演员在幕布拉开前,深吸一口气,告诉自己:好了,舞台已搭好,灯光已就位,观众已入场,表演开始!
跟着代码走这么一圈,虽然很多底层细节(比如ae开头的那些事件循环API的具体实现)我还没深究,但Redis服务器启动的主干流程就清晰多了:准备环境 -> 解析配置 -> 初始化核心组件(尤其是事件循环和网络监听)-> 启动事件循环,开始服务,这个过程不像魔法那样神秘,而是一步一个脚印,逻辑清晰地搭建起来的,下次再遇到Redis启动的问题,我心里就更有底了,知道该去哪个阶段的代码里找原因。
本文由召安青于2026-01-12发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://waw.haoid.cn/wenda/79278.html
