Redis源码分析精通PDF版(redis源码分析pdf)

Redis源码分析:精通PDF版

Redis是一款开源的Key-Value存储数据库,其原理和特点已被广泛涵盖在其他文章中,因此这里不再赘述。本文将由浅入深,逐一分析Redis的源代码,并为初学者提供一份精通Redis源码的PDF版本。

一、基础知识

在开展Redis源码的分析之前,我们需要准备好所需的开发环境,包括Redis的编译环境、C语言基础等。以下是关于Redis基础知识的推荐学习资料:

1.《Redis开发与运维》(原书第2版)

2.《Redis设计与实现》

3.《C Primer Plus》(中文版)

4. 《C程序设计语言》

对于已经具备相关基础知识的开发者,下面将介绍Redis源码的分析。

二、源码结构

Redis的源代码核心代码存放在src目录下,同时还包括一些其他文件,如:

1.测试代码存放在tests目录下

2.默认配置文件存放在配置目录下

3.文档和手册存放在doc目录下

4.扩展模块存放在modules目录下

我们需要在源代码中查找我们需要修改或了解的地方,并编译出Redis的可执行文件。

三、代码分析

从mn函数开始,我们可以看到Redis的启动流程。

首先加载并解析配置文件,然后初始化其他模块(例如网络模块、数据库模块等),最后进入主循环。在主循环中,Redis等待客户端的命令,并根据收到的命令执行相应的操作。

以下是Redis源代码的一部分(src/server.c):

“`c

#include “server.h”

int mn(int argc, char **argv) {

struct timeval tv;

int j;

srand(time(NULL)^getpid());

initServerConfig();

if (argc == 2) {

j = serverLoadConfig(argv[1]);

} else {

j = serverLoadConfig(“/etc/redis/redis.conf”);

if (j == REDIS_ERR) serverLog(LL_WARNING,”Warning: no config file specified, using the default config. In order to specify a config file use %s /path/to/redis.conf”,argv[0]);

}

if (j == REDIS_ERR) exit(1);

initServer();

if (server.daemonize) daemonize();

if (server.pidfile) createPidFile();

if (server.rdb_filename == NULL) server.rdb_filename = zstrdup(“dump.rdb”);

if (server.aof_filename == NULL) server.aof_filename = zstrdup(“appendonly.aof”);

aclInit();

moduleInitModulesSystem();

loadDataFromDisk();

moduleLoadFromQueue();

if (server.cluster_enabled) {

if (verifyClusterConfigWithData() == REDIS_ERR) {

serverLog(LL_WARNING,

“Fled to verify cluster configuration agnst online data. “

“Retrying verification… (Check for errors before the server ‘is able to work’)”);

if (verifyClusterConfigWithData() == REDIS_ERR) {

serverLog(LL_WARNING,”Aborting now.”);

exit(1);

}

}

}

moduleFireServerEvent(REDISMODULE_EVENT_LOADING,0,NULL);

aclLoadUsersFromDisk();

bioInit();

if (server.repl_state == REDIS_REPL_SLAVE) {

if (syncWithMaster(1) == REDIS_ERR) {

serverLog(LL_WARNING,”%s”, “FATAL: The server is not able to synchronize with\nthe master server.”);

exit(1);

}

}

if (server.cluster_enabled && nodeIsSlave(myself)) {

replicationSetMaster(getClusterNodeMaster(), server.port);

}

aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL);

if (!serverSentinelMode) {

if (server.bindaddr_count > 0) {

char ip[16];

int j;

for (j = 0; j

sockaddrToIp(server.bindaddr[j],&ip[0],sizeof(ip));

serverLog(LL_NOTICE,”Binding %s:%d”,ip,server.port);

}

} else {

serverLog(LL_NOTICE,”Server started, Redis version ” REDIS_VERSION);

}

}

adjustOpenFilesLimit();

dictSetHashFunctionSeed(server.hash_seed);

showLogo();

/* When log gets enabled we print an initial log line. */

if (logLevel != LL_NOTICE)

serverLog(logLevel,

“Server started, Redis version ” REDIS_VERSION);

gettimeofday(&tv,NULL);

server.stat_starttime = tv.tv_sec;

/* Things not needed to be done every time the server restarts. */

if (server.stat_starttime != server.lastbgsave_try) {

server.mstime_at_initiate_last_save = mstime();

}

/* Open the listening sockets. */

if (listenToPort(server.port,server.ipfd,&server.ipfd_count) == REDIS_ERR) {

serverLog(LL_WARNING,”Opening port %d: %s”, server.port, strerror(errno));

exit(1);

}

aeCreateFileEvent(server.el, server.ipfd[0], AE_READABLE,

acceptTcpHandler,NULL);

if (server.port && listenToPort(server.tls_port,server.tlsfd,&server.tlsfd_count) == REDIS_ERR) {

serverLog(LL_WARNING,”Opening TLS port %d: %s”, server.tls_port, strerror(errno));

} else if (server.tls_port) {

aeCreateFileEvent(server.el, server.tlsfd[0], AE_READABLE|AE_READ_THREADSAFE,

acceptTLSHandler,NULL);

}

moduleFireServerEvent(REDISMODULE_EVENT_LOADED,0,NULL);

serverLog(LL_NOTICE,”Ready to accept connections”);

aeMn(server.el);

aeDeleteEventLoop(server.el);

return 0;

}


我们可以看到这段代码主要包括加载配置文件、初始化模块、加载数据等操作,最后进入事件处理循环。

在主循环中,Redis使用了一个事件框架(ae),所有的事件被封装成文件事件(File Event)或时间事件(Time Event)进行处理。以下是Redis处理时间事件的示例:

```c
/* =========================== ServerCron ================================ */
void serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
int j;
UNUSED(eventLoop);
UNUSED(id);
UNUSED(clientData);

/* Update the time cache. */
updateCachedTime();
/* Increment various statistics tracked by our "slowlog". */
server.slowlog_tick++;
/* Sample the RSS and other metrics here since it is very cheap to grab
* and we can collect stats with a resolution up to the cron loop
* period if we do so. */
if (server.cronloops % 10 == 0)
processCpuUsed();

/* Record the max length of the client output buffer. */
if (listLength(server.clients) > 0) {
size_t max = getClientOutputBufferMemoryUsage(server.clients->head->value);
if (server.stat_peak_client_output_buffer
server.stat_peak_client_output_buffer = max;
}
/* Close clients that need to be closed asynchronous */
freeClientsInAsyncFreeQueue();
/* Update information about connected clients. */
trackInstantaneousMetric(REDIS_METRIC_COMMAND, (long long) server.stat_numcommands);
trackInstantaneousMetric(REDIS_METRIC_NET_INPUT, server.stat_net_input_bytes);
trackInstantaneousMetric(REDIS_METRIC_NET_OUTPUT, server.stat_net_output_bytes);
trackInstantaneousMetric(REDIS_METRIC_NET_INPUT_BYTES_PER_SEC, server.stat_net_input_bytes_sec);
trackInstantaneousMetric(REDIS_METRIC_NET_OUTPUT_BYTES_PER_SEC, server.stat_net_output_bytes_sec);
trackInstantaneousMetric(REDIS_METRIC_EXPIRED_KEYS, server.stat_expiredkeys);

/*定期执行的操作*/
server.cronloops++;
/* Replication cron function -- used to reconnect to master and
* detect transfer flures. */
replicationCron();
moduleHandleSystemTimerEvents();
aeDeleteTimeEvents(server.el, AE_TIME_EVENT_ALL_IDS);
for (j = 0; j
int i;

/* We have just 10 milliseconds to do everything. The mn goal of
* this first loop is serving the clients: all the other operations
* should be executed as a consequence of the processing we do
* in this loop. */
long long start = ustime();
if (server.cluster_enabled) clusterUpdateState();
if (server.lua_timedout) handleClientsTimeout();
if (server.cluster_migration_barrier_time &&
server.cluster_migration_barrier_time
{
server.cluster_migration

数据运维技术 » Redis源码分析精通PDF版(redis源码分析pdf)