从启动 Redis 服务器, 到服务器可以接受外来客户端的网络连接这段时间, Redis 需要执行一系列初始化操作。
整个初始化过程可以分为以下六个步骤:
- 初始化服务器全局状态。
- 载入配置文件。
- 创建 daemon 进程。
- 初始化服务器功能模块。
- 载入数据。
- 开始事件循环。
以下各个小节将介绍 Redis 服务器初始化的各个步骤。
初始化服务器全局状态
redis.h/redisServer
结构记录了和服务器相关的所有数据, 这个结构主要包含以下信息:
- 服务器中的所有数据库。
- 命令表:在执行命令时,根据字符来查找相应命令的实现函数。
- 事件状态。
- 服务器的网络连接信息:套接字地址、端口,以及套接字描述符。
- 所有已连接客户端的信息。
- 日志(log)和慢查询日志(slowlog)的选项和相关信息。
- 服务器配置选项:比如要创建多少个数据库,是否将服务器进程作为 daemon 进程来运行,最大连接多少个客户端,压缩结构(zip structure)的实体数量,等等。
- 统计信息:比如键有多少次命令、不命中,服务器的运行时间,内存占用,等等。
- 数据持久化(AOF 和 RDB)的配置和状态。
- slave信息
- master信息
- 实现订阅与发布(pub/sub)功能所需的数据结构。
- 是否运行集群及相关选项。
- Lua 脚本的运行环境及相关选项。
- 调试信息选项
/*server对象*/
struct redisServer {
/* General */
//配置文件路径
char *configfile; /* Absolute config file path, or NULL */
//serverCron()调用频率
int hz; /* serverCron() calls frequency in hertz */
//数据库对象
redisDb *db;
//支持的命令列表
dict *commands; /* Command table */
//没有转化的命令
dict *orig_commands; /* Command table before command renaming. */
//事件
aeEventLoop *el;
//每分钟增加一次
unsigned lruclock:22; /* Clock incrementing every minute, for LRU */
unsigned lruclock_padding:10;
int shutdown_asap; /* SHUTDOWN needed ASAP */
int activerehashing; /* Incremental rehash in serverCron() */
//验证密码
char *requirepass; /* Pass for AUTH command, or NULL */
char *pidfile; /* PID file path */
int arch_bits; /* 32 or 64 depending on sizeof(long) */
int cronloops; /* Number of times the cron function run */
char runid[REDIS_RUN_ID_SIZE+1]; /* ID always different at every exec. */
int sentinel_mode; /* True if this instance is a Sentinel. */
/* Networking */
int port; /* TCP listening port */
int tcp_backlog; /* TCP listen() backlog */
char *bindaddr[REDIS_BINDADDR_MAX]; /* Addresses we should bind to */
int bindaddr_count; /* Number of addresses in server.bindaddr[] */
char *unixsocket; /* UNIX socket path */
mode_t unixsocketperm; /* UNIX socket permission */
int ipfd[REDIS_BINDADDR_MAX]; /* TCP socket file descriptors */
int ipfd_count; /* Used slots in ipfd[] */
int sofd; /* Unix socket file descriptor */
int cfd[REDIS_BINDADDR_MAX];/* Cluster bus listening socket */
int cfd_count; /* Used slots in cfd[] */
//连接客户端
list *clients; /* List of active clients */
list *clients_to_close; /* Clients to close asynchronously */
list *slaves, *monitors; /* List of slaves and MONITORs */
redisClient *current_client; /* Current client, only used on crash report */
int clients_paused; /* True if clients are currently paused */
mstime_t clients_pause_end_time; /* Time when we undo clients_paused */
char neterr[ANET_ERR_LEN]; /* Error buffer for anet.c */
dict *migrate_cached_sockets;/* MIGRATE cached sockets */
/* RDB / AOF loading information */
int loading; /* We are loading data from disk if true */
off_t loading_total_bytes;
off_t loading_loaded_bytes;
time_t loading_start_time;
off_t loading_process_events_interval_bytes;
/* Fast pointers to often looked up command */
struct redisCommand *delCommand, *multiCommand, *lpushCommand, *lpopCommand,
*rpopCommand;
/* Fields used only for stats */
time_t stat_starttime; /* Server start time */
long long stat_numcommands; /* Number of processed commands */
long long stat_numconnections; /* Number of connections received */
long long stat_expiredkeys; /* Number of expired keys */