阅读思路
阅读源码的时候应该抓住主干,然后再去各个分支详细分析(个人鄙见)。所以我个人认为redis的启动流程应该是这套源码的主干,所以我先从启动流程下手。对于分析我大致讲个原理,具体详细注释请参照我提交的注释版redis,我在文章中就不再贴源码逐行解释了。
从自己的知识积累出发,先自己预想了下,作为一个服务该有的启动流程。
读取配置->初始化参数->开始网络监听->不断处理网络任务
源码分析
首先查找redis的main函数,不难查找,我们在redis.c这个文件中找到了main函数。
我们这里列出main函数里面主要的几个函数,以下所列函数是按它们在main函数里面的执行顺序。(我们主要分析的是普通节点,哨兵节点的逻辑不在范围内)
//--打散argv和environ所存储内容的空间
spt_init(argc, argv);
//--主要在初始化全局的server对象中的各个数据成员
initServerConfig();
//--继续初始化全局的server对象,并在里面初始化了全局的shared对象
//--监听端口和uinx socket文件
//--启动bio线程
//--lua环境
initServer();
//--检查系统的THP和overcommit_memory
linuxMemoryWarnings();
//--检查tcp_backlog和系统的somaxconn参数值
checkTcpBacklogSettings();
//--根据RDB或者AOF文件加载旧数据,优先AOF文件
loadDataFromDisk();
//--进入事件循环处理
aeMain(server.el);
函数分析
-
spt_init()
redis一开始就把agrv所存储的对象都打散开,是为了后面修改程序名字做铺垫,那为什么改个程序名要这样大费周折呢,那是因为agrv是连续存储的。具体一些知识点我网上找了个资料可以参考下。
-
linuxMemoryWarnings()
redis启动前检测当前系统环境对于内存申请的策略,主要是检查系统里面的/proc/sys/vm/overcommit_memory的文件内容,里面的取值
0 -> 申请的虚拟内存大小大于现有的物理内存时,返回失败
1 -> 忽视现有的物理内存,立即分配虚拟内存,当触发缺页而物理内存不足时可能会被oom进程杀死
2 -> 每次申请都根据现有的物理内存计算出一个阈值,然后跟这个阈值做比较来判断是否允许本次申请
参考资料:http://blog.chinaunix.net/uid-20671208-id-4440244.html
当取到的值为0时,redis会打出警告信息。
-
checkTcpBacklogSettings()
redis启动前进行端口的监听队列的长度检查,通过检查系统的/proc/sys/net/core/somaxconn文件的内容,对于监听队列的长度redis默认是511,由这个值REDIS_TCP_BACKLOG来定义。当取到的值小于server.tcp_backlog,redis会打印出警告信息。
参考资料:http://blog.csdn.net/taolinke/article/details/6800979
以上几个函数我觉得有一些系统知识点的我罗列出来,具体逻辑还是要详见文章开头的源码,后面重点讲讲initServer()和aeMain()这两个函数,我认为是整个启动流程的重点。