08 | Redis server启动后会做哪些操作?
蒋德钧
你好,我是蒋德钧。从这节课开始,我们就来到了课程的第二个模块,在这个模块里,我会带你了解和学习与 Redis 实例运行相关方面的知识,包括 Redis server 的启动过程、基于事件驱动框架的网络通信机制以及 Redis 线程执行模型。今天,我们先来学习下 Redis server 的启动过程。
我们知道,main 函数是 Redis 整个运行程序的入口,并且 Redis 实例在运行时,也会从这个 main 函数开始执行。同时,由于 Redis 是典型的 Client-Server 架构,一旦 Redis 实例开始运行,Redis server 也就会启动,而 main 函数其实也会负责 Redis server 的启动运行。
你平常在设计或实现一个网络服务器程序时,可能会遇到一个问题,那就是服务器启动时,应该做哪些操作、有没有一个典型的参考实现。所以今天这节课,我就从 main 函数开始,给你介绍下 Redis server 是如何在 main 函数中启动并完成初始化的。通过这节课内容的学习,你可以掌握 Redis 针对以下三个问题的实现思路:
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
Redis server的启动过程包括五个阶段:基本初始化、检查哨兵模式、运行参数解析、初始化server和执行事件驱动框架。在基本初始化阶段,main函数完成一些基本的初始化工作,包括设置时区和哈希函数的随机种子。在检查哨兵模式阶段,main函数检查是否设置了哨兵模式,并进行相应的初始化设置。运行参数解析阶段对命令行传入的参数进行解析,并调用loadServerConfig函数进行合并处理。初始化server阶段调用initServer函数对server运行时的各种资源进行初始化工作。最后,在执行事件驱动框架阶段,main函数调用aeMain函数进入事件驱动框架,开始循环处理各种触发的事件。 Redis的主要参数类型包括通用参数、数据结构参数、网络参数、持久化参数、主从复制参数、切片集群参数和性能优化参数。这些参数与Redis的主要功能机制相对应,对这些参数的典型配置值需要对相应功能机制的工作原理有所了解。 通过本文,读者可以了解Redis server启动过程的五个阶段,以及Redis的主要参数类型,帮助读者快速了解Redis server的运行机制和参数配置。文章还介绍了main函数的设计和实现思路,强调了运行参数解析、server初始化和执行事件驱动框架是Redis sever启动过程中的三个关键阶段。这些内容对于开发网络服务器和解决Redis使用中的疑惑都具有参考价值。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Redis 源码剖析与实战》,新⼈⾸单¥59
《Redis 源码剖析与实战》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(12)
- 最新
- 精选
- KaitoRedis 启动流程,主要的工作有: 1、初始化前置操作(设置时区、随机种子) 2、初始化 Server 的各种默认配置(server.c 的 initServerConfig 函数),默认配置见 server.h 中的 CONFIG_DEFAULT_XXX,比较典型的配置有: - 默认端口 - 定时任务频率 - 数据库数量 - AOF 刷盘策略 - 淘汰策略 - 数据结构转换阈值 - 主从复制参数 3、加载配置启动参数,覆盖默认配置(config.c 的 loadServerConfig 函数): - 解析命令行参数 - 解析配置文件 3、初始化 Server(server.c 的 initServer 函数),例如会初始化: - 共享对象池 - 客户端链表 - 从库链表 - 监听端口 - 全局哈希表 - LRU 池 - 注册定时任务函数 - 注册监听请求函数 4、启动事件循环(ae.c 的 aeMain 函数) - 处理请求 - 处理定时任务 这里补充一下,初始化 Server 完成后,Redis 还会启动 3 类后台线程(server.c 的 InitServerLast 函数),协助主线程工作(异步释放 fd、AOF 每秒刷盘、lazyfree)。 课后题:Redis 源码的 main 函数在调用 initServer 函数之前,会执行如下的代码片段,你知道这个代码片段的作用是什么吗? int main(int argc, char **argv) { ... server.supervised = redisIsSupervised(server.supervised_mode); int background = server.daemonize && !server.supervised; if (background) daemonize(); ... } Redis 可以配置以守护进程的方式启动(配置文件 daemonize = yes),也可以把 Redis 托管给 upstart 或 systemd 来启动 / 停止(supervised = upstart|systemd|auto)。2021-08-12631
- 曾轼麟感谢老师的文章,先回答老师提出的问题:文章中代码片段的作用是?根据关键词我找到代码位于,main函数中loadServerConfig之后执行的,那么这块代码主要任务和顺序如下所示: 1、此时redis的config是已经初始化完成的 2、执行redisIsSupervised其目底主要是判断当redis进程是否运行中 3、判断daemonize是否开启(如果启动设置了daemonize参数那么这里参数已经被填充) 4、之前并没有存活的redis实例,并且开启了daemonize配置,那么执行daemonize函数挂起后台运行 这里需要解释一下,执行daemonize()函数的时候本质是fork()进程,并不是大多文章说的那样是守护线程,父亲fork成功后是直接退出(在前端的效果就是,启动命令任务完成但是ps是有一个redis的进程),剩余的任务是交给fork出的子进程完成的(可以参考《深入理解操作系统》 第8章-异常控制流-进程中的内容) 读完这篇文章后,我个人尝试画出整个redis启动的时序图,发现整个思路就很清晰了,建议同样阅读文章的同学可以尝试画一下,我总结一下我读完文章后的理解: 1、redis的整体启动流程是按照 【初始化默认配置】->【解析启动命令】->【初始化server】->【初始化并启动事件驱动框架】 进行 2、整个运行中的redis,其实就是一个永不停歇的while循环,位于aeMain中(运行中的事件驱动框架) 3、在事件驱动框架中有两个钩子函数 beforeSleep 和 aftersleep,在每次while循环中都会触发这两个函数,后面用来实现事件触发的效果 此外我发现了一个细节点:我在近期版本的redis6的分支上,发现在启动事件驱动框架之前(执行aeMain之前)会执行一个redisSetCpuAffinity函数,其效果有点类似于绑核的效果,那么是否可以认为从redis6开始其实不需要运维帮忙绑核redis自身就能做到绑核的效果呢?2021-08-13210
- 木几丶简易版启动流程: 初始化默认配置->解析启动参数和配置文件覆盖默认配置->初始化server->启动事件驱动框架2021-08-2913
- 零点999mac环境下使用clion软件debug redis源码的配置过程: https://www.toutiao.com/article/7214017532637004346/?log_from=bc6912dd0e87f_16796997580132023-03-25归属地:英国1
- 零点999server.supervised = redisIsSupervised(server.supervised_mode);int background = server.daemonize && !server.supervised;if (background) daemonize();...} Redis 可以配置以守护进程的方式启动(配置文件 daemonize = yes)2023-03-25归属地:北京
- 瞭望站在风口的猪老师好,我发现有一处逻辑错了,是先检查RBD再检查AOF吧 if (strstr(argv[0],"redis-check-rdb") != NULL) redis_check_rdb_main(argc,argv,NULL); else if (strstr(argv[0],"redis-check-aof") != NULL) redis_check_aof_main(argc,argv);2022-09-27归属地:北京1
- lzh2nix在这一讲中大部分逻辑都是在initSerer中完成,所以对initSerer函数的理解也是重中之重。 initSerer(void initServer(void)) \ 1. server 结构体的初始化 2. sharedObject 创建(createSharedObjects()) 3. 创建事件驱动框架(aeCreateEventLoop()) 4. 监听tcp端口(listenToPort()) 5. 监听unix socket(anetUixServer()) 6. redis DB 初始化 7. 系统状态设置(staat/cron/aof/rdb 等状态) 8. 将timer事件添加到eventLoop中(aeCreateTimeEvent(...serverCron)) 9. 接受tcp连接事件添加到eventLoop中(aeCreateFileEvent(...acceptTcpEVent)) 10. 接受到unix socket连接的事件添加到eventLoop中(aeCreateFileEvent(acceptUnixHandler)) 11. server中cluster 相关配置的初始化 12. replicationScriptCacheInit()/scriptingInit()/scriptingInit()/latencyMonitorInit()2021-08-23
- lzh2nix在这一讲中大部分逻辑都是在initSerer中完成,所以对initSerer函数的理解也是重中之重。 initSerer(void initServer(void)) \ 1. server 结构体的初始化 2. sharedObject 创建(createSharedObjects()) 3. 创建事件驱动框架(aeCreateEventLoop()) 4. 监听tcp端口(listenToPort()) 5. 监听unix socket(anetUixServer()) 6. redis DB 初始化 7. 系统状态设置(staat/cron/aof/rdb 等状态) 8. 将timer事件添加到eventLoop中(aeCreateTimeEvent(...serverCron)) 9. 接受tcp连接事件添加到eventLoop中(aeCreateFileEvent(...acceptTcpEVent)) 10. 接受到unix socket连接的事件添加到eventLoop中(aeCreateFileEvent(acceptUnixHandler)) 11. server中cluster 相关配置的初始化 12. replicationScriptCacheInit()/scriptingInit()/scriptingInit()/latencyMonitorInit()2021-08-23
- haha老师的这些图是用什么软件画的啊2021-08-211
- 末日,成欢起始处设置随机种子是为了做什么?2021-08-123
收起评论