新聞中心
Redis源碼分析:精通PDF版

Redis是一款開源的Key-Value存儲數據庫,其原理和特點已被廣泛涵蓋在其他文章中,因此這里不再贅述。本文將由淺入深,逐一分析Redis的源代碼,并為初學者提供一份精通Redis源碼的PDF版本。
一、基礎知識
在開展Redis源碼的分析之前,我們需要準備好所需的開發(fā)環(huán)境,包括Redis的編譯環(huán)境、C語言基礎等。以下是關于Redis基礎知識的推薦學習資料:
1.《Redis開發(fā)與運維》(原書第2版)
2.《Redis設計與實現(xiàn)》
3.《C Primer Plus》(中文版)
4. 《C程序設計語言》
對于已經具備相關基礎知識的開發(fā)者,下面將介紹Redis源碼的分析。
二、源碼結構
Redis的源代碼核心代碼存放在src目錄下,同時還包括一些其他文件,如:
1.測試代碼存放在tests目錄下
2.默認配置文件存放在配置目錄下
3.文檔和手冊存放在doc目錄下
4.擴展模塊存放在modules目錄下
我們需要在源代碼中查找我們需要修改或了解的地方,并編譯出Redis的可執(zhí)行文件。
三、代碼分析
從mn函數開始,我們可以看到Redis的啟動流程。
首先加載并解析配置文件,然后初始化其他模塊(例如網絡模塊、數據庫模塊等),最后進入主循環(huán)。在主循環(huán)中,Redis等待客戶端的命令,并根據收到的命令執(zhí)行相應的操作。
以下是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,”O(jiān)pening 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,”O(jiān)pening 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;
}
我們可以看到這段代碼主要包括加載配置文件、初始化模塊、加載數據等操作,最后進入事件處理循環(huán)。
在主循環(huán)中,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);
/*定期執(zhí)行的操作*/
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
成都創(chuàng)新互聯(lián)科技公司主營:網站設計、網站建設、小程序制作、成都軟件開發(fā)、網頁設計、微信開發(fā)、成都小程序開發(fā)、網站制作、網站開發(fā)等業(yè)務,是專業(yè)的成都做小程序公司、成都網站建設公司、成都做網站的公司。創(chuàng)新互聯(lián)公司集小程序制作創(chuàng)意,網站制作策劃,畫冊、網頁、VI設計,網站、軟件、微信、小程序開發(fā)于一體。
網頁題目:Redis源碼分析精通PDF版(redis源碼分析pdf)
標題路徑:http://m.fisionsoft.com.cn/article/cdgsess.html


咨詢
建站咨詢
