Redis源码分析之启动流程
-
源码版本:5.0
-
main 函数
-
servecron 函数
-
acceptTcpHandler 函数
-
时序图源码:
-
main 函数
@startuml
group main
server.c -> setproctitle.c : spt_init():为函数setproctitle调用做初始化工作
server.c -> server.c : setlocale(LC_COLLATE,""); 设置本地化
server.c -> server.c : tzset();
server.c -> server.c : zmalloc_set_oom_handler(redisOutOfMemoryHandler);
server.c -> server.c : srand(time(NULL)^getpid());
server.c -> server.c : gettimeofday(&tv,NULL);
server.c -> dict.c : dictSetHashFunctionSeed((uint8_t*)hashseed); 设置hash函数随机种子
server.c -> server.c : checkForSentinelMode() 检查哨兵模式
server.c -> server.c : initServerConfig() 初始化server配置
server.c -> module.c : moduleInitModulesSystem() 初始化module系统
server.c -> server.c : 保存argc和argv
group #LightYellow 如果是哨兵模式
server.c -> sentinel.c : initSentinelConfig() 初始化哨兵配置
server.c -> sentinel.c : initSentinel() 初始化哨兵
end
server.c -> redis_check_rdb.c : redis_check_rdb_main() 如果是通过redis-check-rdb启动,执行rdb检查
redis_check_rdb.c -> END : 结束
server.c -> redis_check_aof.c : redis_check_aof_main() 如果是通过redis-check-aof启动,执行aof检查,然后返回
redis_check_aof.c -> END : 结束
server.c -> config.c : loadServerConfig() 根据配置文件和命令行参数设置server
server.c -> server.c : 打印启动信息
server.c -> server.c : 根据配置决定是否后台进程启动
server.c -> server.c : initServer() 初始化服务器
group #Yellow initServer
server.c -> server.c : setupSignalHandlers() 设置信号处理函数
server.c -> server.c : 根据配置决定是否开启系统日志
server.c -> server.c : 初始化server对象用到的的结构体:list、rax等
server.c -> server.c : createSharedObjects() 创建共享对象
server.c -> server.c : adjustOpenFilesLimit() 适配打开文件数限制
server.c -> ae.c : aeCreateEventLoop() 创建事件循环对象el
server.c -> server.c : listenToPort() 开启本地端口监听
group #LightBlue listenToPort
server.c -> anet.c : anetTcpServer()
group #LightPink anetTcpServer
anet.c -> system : socket() 创建服务端socket
anet.c -> anet.c : anetSetReuseAddr() 设置地址重用
anet.c -> system : bind() 绑定本地地址
anet.c -> system : listen() 开始监听端口
end
server.c -> anet.c : anetNonBlock() 设置非阻塞监听
end
server.c -> server.c : 初始化默认的16个数据库对象
server.c -> evict.c : evictionPoolAlloc() 初始化内存淘汰池
server.c -> server.c : 初始化server的其他字段
server.c -> ae.c : aeCreateTimeEvent() 创建时间处理事件,处理函数为serverCron
server.c -> networking.c : aeCreateFileEvent() 绑定socket到el,监听读事件,处理函数为acceptTcpHandler
server.c -> networking.c : aeCreateFileEvent() 绑定module的管道到el,监听读事件,处理函数为moduleBlockedClientPipeReadable
server.c -> server.c : 如果开启了AOF,则打开AOF文件
server.c -> server.c : 32位系统没有设置内存限制,默认设置为3G,缓存不淘汰
server.c -> cluster.c : clusterInit() 开启了集群能力,则进行集群初始化工作
server.c -> replication.c : replicationScriptCacheInit() 备份脚本缓存初始化
server.c -> script.c : scriptingInit() 脚本初始化
server.c -> slowlog.c : slowlogInit() 慢日志初始化
server.c -> latency.c : latencyMonitorInit() 延迟监控初始化
end
server.c -> server.c : 有必要则创建pid文件
server.c -> setproctitle.c : redisSetProcTitle() 设置进程名称
server.c -> server.c : redisAsciiArt() 打印logo
server.c -> server.c : checkTcpBacklogSettings() 检查系统tcp backlog,小于当前设置则打印警告
alt#Gold #LightYellow 非哨兵模式
server.c -> server.c : 执行系统相关检查
server.c -> module.c : moduleLoadFromQueue() 模块加载
server.c -> server.c : InitServerLast() 初始化后置操作
group #LightBlue InitServerLast
server.c -> bio.c : bioInit() 初始化后台线程
server.c -> server.c : server.initial_memory_usage参数
end
server.c -> server.c : loadDataFromDisk() 从磁盘加载数据
group #LightGreen loadDataFromDisk 优先加载aof,没有则加载rdb
server.c -> aof.c : loadAppendOnlyFile() 加载aof文件
server.c -> rdb.c : rdbLoad() 加载rdb文件
end
server.c -> cluster.c : verifyClusterConfigWithData() 如果开启了集群模式,进行集群配置验证
else #Yellow 哨兵模式
group #LightBlue InitServerLast
server.c -> bio.c : bioInit() 初始化后台线程
server.c -> server.c : server.initial_memory_usage参数
end
server.c -> sentinel.c : sentinelIsRunning()
end
server.c -> ae.c : aeSetBeforeSleepProc() 设置休眠前处理函数beforeSleep
server.c -> ae.c : aeSetAfterSleepProc() 设置休眠后处理函数afterSleep
server.c -> ae.c : aeMain() 开始事件循环,正常启动后会一直循环
server.c -> ae.c : aeDeleteEventLoop() 删除事件循环,释放事件循环资源
end
@enduml
- servercron 函数
@startuml
server.c -> server.c : servercron()
group #LightYellow servercron
server.c -> debug.c : watchdogScheduleSignal() 设置了watchdog_period参数,调度SIGALRM信号
server.c -> server.c : updateCachedTime() 更新缓存的时间
server.c -> server.c : 设置自动更新或者手动设置的频率hz
group #yellow 每100ms执行一次
server.c -> server.c : trackInstantaneousMetric() 更新服务器采样STATS_METRIC_COMMAND
server.c -> server.c : trackInstantaneousMetric() 更新服务器采样STATS_METRIC_NET_INPUT
server.c -> server.c : trackInstantaneousMetric() 更新服务器采样STATS_METRIC_NET_OUTPUT
end
server.c -> server.c : 更新LRU时钟
server.c -> server.c : 更新服务器内存使用峰值
group #yellow 每100ms执行一次
server.c -> server.c : 更新内存使用统计cron_malloc_stats
end
server.c -> server.c : 响应停机信号
group #yellow 每5s执行一次
server.c -> server.c : 打印VERBOSE级别的DB统计信息
end
group #yellow 非哨兵模式下,每5s执行一次
server.c -> server.c : 打印VERBOSE级别的客户端信息
end
server.c -> server.c : clientsCron()
group #yellow clientsCron
loop 遍历总数/hz个客户端
server.c -> server.c : 把链表尾部的客户端移动到链表开头
server.c -> server.c : clientsCronHandleTimeout() 处理客户端超时
server.c -> server.c : clientsCronResizeQueryBuffer() 整理客户端的queryBuffer
server.c -> server.c : clientsCronTrackExpansiveClients() 统计大流量客户端Top8
end
end
server.c -> server.c : databasesCron()
group #yellow databasesCron
alt #Pink master
server.c -> expire.c : activeExpireCycle()
else #LightBlue slave
server.c -> expire.c : expireSlaveKeys()
end
server.c -> defrag.c : activeDefragCycle() 开启了内存碎片整理,则执行
server.c -> server.c : 没有RDB和AOF子进程,对DB进行扩容,执行1ms的增量rehash
end
server.c -> aof.c : rewriteAppendOnlyFileBackground() 没有RDB和AOF子进程,设置了AOF重写,则执行
alt #Pink 有RDB或AOF子进程或ldbPendingChildren()
server.c -> server.c : 等待子进程执行,执行对应收尾
else #LightBlue
server.c -> rdb.c : rdbSaveBackground() 根据save配置决定执行RDB保存
server.c -> aof.c : rewriteAppendOnlyFileBackground() 根据条件决定执行AOF重写
end
server.c -> aof.c : flushAppendOnlyFile() 根据aof_flush_postponed_start决定是否刷新AOF文件
group #yellow 每1s执行一次
server.c -> aof.c : flushAppendOnlyFile() 如果aof_last_write_status为err
end
server.c -> networking.c : freeClientsInAsyncFreeQueue() 异步释放客户端
server.c -> networking.c : clientsArePaused()
group #yellow 每1s执行一次
server.c -> replication.c : replicationCron() 执行备份调度函数
end
group #yellow 每1s执行一次
server.c -> cluster.c : clusterCron() 执行集群调度函数
end
server.c -> sentinel.c : sentinelTimer 如果是哨兵模式,执行哨兵调度函数
group #yellow 每1s执行一次
server.c -> cluster.c : migrateCloseTimedoutSockets()
end
server.c -> server.c : 执行被延迟的bgsave,如有
end
@enduml
- acceptTcpHandler 函数
@startuml
networking.c -> networking.c : acceptTcpHandler 服务端socket处理函数
loop #LightYellow 1000
networking.c -> anet.c : anetTcpAccept() 获取Tcp连接
anet.c -> system : accept()
networking.c <- anet.c : anetTcpAccept() 返回客户端fd
networking.c -> networking.c : acceptCommonHandler() 处理客户端fd
group #Yellow acceptCommonHandler
networking.c -> networking.c : createClient() 创建客户端对象
group #Red createClient
networking.c -> anet.c : anetNonBlock() 设置非阻塞
networking.c -> anet.c : anetEnableTcpNoDelay() 设置无延迟
networking.c -> anet.c : anetKeepAlive() 根据配置设置keepalive
networking.c -> ae.c : aeCreateFileEvent() 注册到事件循环el上,处理函数为readQueryFromClient
networking.c -> db.c : selectDb() 选中0号DB
networking.c -> networking.c : 初始化客户端数据
networking.c -> networking.c : linkClient()把客户端放进客户端链表
networking.c -> multi.c : initClientMultiState() 初始化客户端事务数据
end
networking.c -> networking.c : 如果客户端连接数超限制,返回错误并关闭
networking.c -> networking.c : 如果客户端不满足安全要求,返回错误并关闭
end
end
@enduml