Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
94 lines (53 sloc) 4.13 KB

#redis-server启动的主流程

我们从 redis-server(src/redis.c) 启动说起,随着 main 函数浏览一下各个关键函数,了解一下 Redis 的主要程序流程。

Redis-server-start

##initServerConfig

initServerConfig函数会给 server(RedisServer) 这个全局变量设置一些默认的参数,比如监听端口为 6379 ,默认的内置 db 个数为 16 等。默认值对于一个用户友好的软件非常重要,谁愿意第一次使用软件还要设置一大堆云里雾里的参数呢?所有的参数后面会详细讲述。

RedisServer 这个结构非常重要,是 Redis 服务端程序唯一的一个结构体,稍后我们会详细介绍这个结构体成员的作用。

    server.commands = dictCreate(&commandTableDictType,NULL);
    populateCommandTable();                     
    server.delCommand = lookupCommandByCString("del");
    server.multiCommand = lookupCommandByCString("multi");

PopulateCommandTable会把命令与函数数组readonlyCommandTable数组结构保存到哈希表结构 server.commands,方便跨速查找。例如用户键入了set a 1这个命令到服务端,服务端解析协议后知道了set 这个命令,就可以找到setCommand这个相应的处理函数,这个后面会详细描述。

另外好保存 del,multi命令的指针,方便更快速的使用。

    server.slowlog_log_slower_than = REDIS_SLOWLOG_LOG_SLOWER_THAN;
    server.slowlog_max_len = REDIS_SLOWLOG_MAX_LEN;

慢日志参数的配置,凡是超过 REDIS_SLOWLOG_LOG_SLOWER_THAN 时间的命令会被记录到慢日志里,慢日志最多能存储 REDIS_SLOWLOG_MAX_LEN 条记录。

##loadServerConfig

如果redis-server启动参数里有指定redis.confLoadServerConfig函数就会读入redis.conf里的参数,覆盖之前的默认值。

##initServer

  • 利用signal屏蔽一些信号,设置一些信号处理函数setupSignalHandlers

  • 再次对 redis-server 这个数据结构做初始化。

  • createSharedObjects 提前产生一些常用的对象,避免临时 malloc。

  • aeCreateEventLoop 创建多路服务的文件、事件事件管理器。

  • anetTcpServer 启动 6379 端口的监听。

  • anetUnixServer 启动unix socket 的监听。

  • 添加文件和时间事件。

    1. 添加一个时间事件,函数是serverCron。这个函数会每 100ms 执行一次,后面会详细描述这个函数的作用。
    2. 添加一个监听的文件事件,把 accept 行为注册到只读的监听文件描述符上,回凋函数是acceptTcpHandler
  • slowlogInit 启动慢日志功能,发现比较慢的命令。

  • bioInit 启动后台线程来处理系统调用耗时的操作。

##aeMain(el)

进入 Redis 的主循环。

每次循环之前还会执行beforeSleep

然后开始循环,这个循环目前每隔 100ms 会执行一次serverCron函数,并仅仅盯着监听的 fd,等待外部的连接,有连接则调用acceptTcpHandler

##beforeSleep

  • 清理unblocked_clients??
  • 处理尚未处理的数据,调用 processInputBuffer 为什么还会有数据呢?
  • flushAppendOnlyFile

##serverCron

时间事件serverCron需要做很多事情。

  • 更新lruclock
  • 每50次,打印出库内键值状况
  • 每10次,resize 哈希表??
  • 调用 incrementallyRehash 增量哈希
  • 关闭长时间不工作的 client。
  • 处理 bgsave 或者 bgrewriteaof 的子进程退出后的收尾工作。
  • rewriteAppendOnlyFileBackground ??
  • 根据键值的变化判断是否需要启动子进程做快照,或者根据AOF文件的当前状况判断是否需要启动子进程执行 AOF 文件重整理工作。
  • 如果激活 AOF 延迟刷到磁盘机制,则执行一次 AOF 文件的刷到磁盘
  • 如果是主库,清理过期(expire)的 键值。
  • 每10次,也就是1s,执行 replicationCron,如果自己是主库,会检测备库节点的状况,如果自己是备库,会连接主库。

##acceptTcpHandler

现在来看redis-server如何处理网络连接,见下一章。