server.c - main函数
- 初始化系统设置(时区,随机数种子,ACL,TLS等)
- 加载配置,覆盖默认配置
- 初始化server
- 开始接受请求,并循环处理事件
setlocale(LC_COLLATE,"");
tzset();
zmalloc_set_oom_handler(redisOutOfMemoryHandler);
srand(time(NULL)^getpid());
srandom(time(NULL)^getpid());
gettimeofday(&tv,NULL);
crc64_init();
getRandomBytes(hashseed,sizeof(hashseed));
dictSetHashFunctionSeed(hashseed);
server.sentinel_mode = checkForSentinelMode(argc,argv);
initServerConfig();
ACLInit();
moduleInitModulesSystem();
tlsInit();
if (server.sentinel_mode) {
initSentinelConfig();
initSentinel();
}
loadServerConfig(server.configfile, config_from_stdin, options);
if (background) daemonize();
readOOMScoreAdj();
initServer();
if (background || server.pidfile) createPidFile();
redisSetProcTitle(argv[0]);
redisAsciiArt();
checkTcpBacklogSettings();
if (!server.sentinel_mode) {
moduleInitModulesSystemLast();
moduleLoadFromQueue();
ACLLoadUsersAtStartup();
InitServerLast();
loadDataFromDisk();
} else {
ACLLoadUsersAtStartup();
InitServerLast();
sentinelIsRunning();
}
redisSetCpuAffinity(server.server_cpulist);
setOOMScoreAdj(-1);
aeMain(server.el);
aeDeleteEventLoop(server.el);
initServer函数
- 注册信号监听
- 初始化全局server对象
- 打开listen端口,参考listenToPort
- 创建db并初始化
- 初始化server的rdb、aof、child、stat等信息
- 注册定时任务回调以待后续启动定时任务serverCron
- 开始accept
- 打开aof文件(按需)
- 初始化redis-cluster(按需)
- 初始化lua脚本环境
- 初始化slowlog和latencyMonitor存储dict
void initServer(void) {
int j
signal(SIGHUP, SIG_IGN)
signal(SIGPIPE, SIG_IGN)
setupSignalHandlers()
makeThreadKillable()
if (server.syslog_enabled) {
openlog(server.syslog_ident, LOG_PID | LOG_NDELAY | LOG_NOWAIT,
server.syslog_facility)
}
/* Initialization after setting defaults from the config system. */
server.aof_state = server.aof_enabled ? AOF_ON : AOF_OFF
server.hz = server.config_hz
server.pid = getpid()
server.in_fork_child = CHILD_TYPE_NONE
server.main_thread_id = pthread_self()
server.current_client = NULL
server.fixed_time_expire = 0
server.clients = listCreate()
server.clients_index = raxNew()
server.clients_to_close = listCreate()
server.slaves = listCreate()
server.monitors = listCreate()
server.clients_pending_write = listCreate()
server.clients_pending_read = listCreate()
server.clients_timeout_table = raxNew()
server.slaveseldb = -1
server.unblocked_clients = listCreate()
server.ready_keys = listCreate()
server.clients_waiting_acks = listCreate()
server.get_ack_from_slaves = 0
server.clients_paused = 0
server.events_processed_while_blocked = 0
server.system_memory_size = zmalloc_get_memory_size()
if ((server.tls_port || server.tls_replication || server.tls_cluster)
&& tlsConfigure(&server.tls_ctx_config) == C_ERR) {
serverLog(LL_WARNING, "Failed to configure TLS. Check logs for more info.")
exit(1)
}
createSharedObjects()
adjustOpenFilesLimit()
const char *clk_msg = monotonicInit()
serverLog(LL_NOTICE, "monotonic clock: %s", clk_msg)
server.el = aeCreateEventLoop(server.maxclients+CONFIG_FDSET_INCR)
if (server.el == NULL) {
serverLog(LL_WARNING,
"Failed creating the event loop. Error message: '%s'",
strerror(errno))
exit(1)
}
server.db = zmalloc(sizeof(redisDb)*server.dbnum)
/* Open the TCP listening socket for the user commands. */
if (server.port != 0 &&
listenToPort(server.port,server.ipfd,&server.ipfd_count) == C_ERR)
exit(1)
if (server.tls_port != 0 &&
listenToPort(server.tls_port,server.tlsfd,&server.tlsfd_count) == C_ERR)
exit(1)
/* Open the listening Unix domain socket. */
if (server.unixsocket != NULL) {
unlink(server.unixsocket)
server.sofd = anetUnixServer(server.neterr,server.unixsocket,
server.unixsocketperm, server.tcp_backlog)
if (server.sofd == ANET_ERR) {
serverLog(LL_WARNING, "Opening Unix socket: %s", server.neterr)
exit(1)
}
anetNonBlock(NULL,server.sofd)
}
/* Abort if there are no listening sockets at all. */
if (server.ipfd_count == 0 && server.tlsfd_count == 0 && server.sofd < 0) {
serverLog(LL_WARNING, "Configured to not listen anywhere, exiting.")
exit(1)
}
/* Create the Redis databases, and initialize other internal state. */
for (j = 0
server.db[j].dict = dictCreate(&dbDictType,NULL)
server.db[j].expires = dictCreate(&keyptrDictType,NULL)
server.db[j].expires_cursor = 0
server.db[j].blocking_keys = dictCreate(&keylistDictType,NULL)
server.db[j].ready_keys = dictCreate(&objectKeyPointerValueDictType,NULL)
server.db[j].watched_keys = dictCreate(&keylistDictType,NULL)
server.db[j].id = j
server.db[j].avg_ttl = 0
server.db[j].defrag_later = listCreate()
listSetFreeMethod(server.db[j].defrag_later,(void (*)(void*))sdsfree)
}
evictionPoolAlloc()
server.pubsub_channels = dictCreate(&keylistDictType,NULL)
server.pubsub_patterns = listCreate()
server.pubsub_patterns_dict = dictCreate(&keylistDictType,NULL)
listSetFreeMethod(server.pubsub_patterns,freePubsubPattern)
listSetMatchMethod(server.pubsub_patterns,listMatchPubsubPattern)
server.cronloops = 0
server.rdb_child_pid = -1
server.aof_child_pid = -1
server.module_child_pid = -1
server.rdb_child_type = RDB_CHILD_TYPE_NONE
server.rdb_pipe_conns = NULL
server.rdb_pipe_numconns = 0
server.rdb_pipe_numconns_writing = 0
server.rdb_pipe_buff = NULL
server.rdb_pipe_bufflen = 0
server.rdb_bgsave_scheduled = 0
server.child_info_pipe[0] = -1
server.child_info_pipe[1] = -1
server.child_info_data.magic = 0
aofRewriteBufferReset()
server.aof_buf = sdsempty()
server.lastsave = time(NULL)
server.lastbgsave_try = 0
server.rdb_save_time_last = -1
server.rdb_save_time_start = -1
server.dirty = 0
resetServerStats()
/* A few stats we don't want to reset: server startup time, and peak mem. */
server.stat_starttime = time(NULL)
server.stat_peak_memory = 0
server.stat_rdb_cow_bytes = 0
server.stat_aof_cow_bytes = 0
server.stat_module_cow_bytes = 0
for (int j = 0
server.stat_clients_type_memory[j] = 0
server.cron_malloc_stats.zmalloc_used = 0
server.cron_malloc_stats.process_rss = 0
server.cron_malloc_stats.allocator_allocated = 0
server.cron_malloc_stats.allocator_active = 0
server.cron_malloc_stats.allocator_resident = 0
server.lastbgsave_status = C_OK
server.aof_last_write_status = C_OK
server.aof_last_write_errno = 0
server.repl_good_slaves_count = 0
//注册定时任务回调以待后续启动定时任务
/* Create the timer callback, this is our way to process many background
* operations incrementally, like clients timeout, eviction of unaccessed
* expired keys and so forth. */
if (aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL) == AE_ERR) {
serverPanic("Can't create event loop timers.")
exit(1)
}
/* Create an event handler for accepting new connections in TCP and Unix
* domain sockets. */
for (j = 0
if (aeCreateFileEvent(server.el, server.ipfd[j], AE_READABLE,
acceptTcpHandler,NULL) == AE_ERR)
{
serverPanic(
"Unrecoverable error creating server.ipfd file event.")
}
}
for (j = 0
if (aeCreateFileEvent(server.el, server.tlsfd[j], AE_READABLE,
acceptTLSHandler,NULL) == AE_ERR)
{
serverPanic(
"Unrecoverable error creating server.tlsfd file event.")
}
}
if (server.sofd > 0 && aeCreateFileEvent(server.el,server.sofd,AE_READABLE,
acceptUnixHandler,NULL) == AE_ERR) serverPanic("Unrecoverable error creating server.sofd file event.")
/* Register a readable event for the pipe used to awake the event loop
* when a blocked client in a module needs attention. */
if (aeCreateFileEvent(server.el, server.module_blocked_pipe[0], AE_READABLE,
moduleBlockedClientPipeReadable,NULL) == AE_ERR) {
serverPanic(
"Error registering the readable event for the module "
"blocked clients subsystem.")
}
/* Register before and after sleep handlers (note this needs to be done
* before loading persistence since it is used by processEventsWhileBlocked. */
aeSetBeforeSleepProc(server.el,beforeSleep)
aeSetAfterSleepProc(server.el,afterSleep)
/* Open the AOF file if needed. */
if (server.aof_state == AOF_ON) {
server.aof_fd = open(server.aof_filename,
O_WRONLY|O_APPEND|O_CREAT,0644)
if (server.aof_fd == -1) {
serverLog(LL_WARNING, "Can't open the append-only file: %s",
strerror(errno))
exit(1)
}
}
/* 32 bit instances are limited to 4GB of address space, so if there is
* no explicit limit in the user provided configuration we set a limit
* at 3 GB using maxmemory with 'noeviction' policy'. This avoids
* useless crashes of the Redis instance for out of memory. */
if (server.arch_bits == 32 && server.maxmemory == 0) {
serverLog(LL_WARNING,"Warning: 32 bit instance detected but no memory limit set. Setting 3 GB maxmemory limit with 'noeviction' policy now.")
server.maxmemory = 3072LL*(1024*1024)
server.maxmemory_policy = MAXMEMORY_NO_EVICTION
}
if (server.cluster_enabled) clusterInit()
replicationScriptCacheInit()
scriptingInit(1)
slowlogInit()
latencyMonitorInit()
}