新聞中心
Redis是一個(gè)廣泛使用的內(nèi)存鍵值數(shù)據(jù)庫,被許多大公司用于存儲(chǔ)臨時(shí)數(shù)據(jù)、緩存和消息隊(duì)列等用途。了解Redis的內(nèi)部實(shí)現(xiàn)有助于我們更好地利用它的功能,調(diào)優(yōu)它的性能并發(fā)控制,并能夠更多地利用Redis作為自己系統(tǒng)的架構(gòu)組件。因此,本文將對Redis的源代碼進(jìn)行網(wǎng)絡(luò)分析,解讀Redis的內(nèi)部實(shí)現(xiàn)。

我們提供的服務(wù)有:成都網(wǎng)站建設(shè)、網(wǎng)站制作、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、安州ssl等。為近千家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的安州網(wǎng)站制作公司
Redis的網(wǎng)絡(luò)編程實(shí)現(xiàn)
Redis采用C語言編寫,其網(wǎng)絡(luò)編程基于Event Loop設(shè)計(jì),使用多路復(fù)用技術(shù)。在Redis啟動(dòng)時(shí),它會(huì)創(chuàng)建一個(gè)Socket監(jiān)聽器用于監(jiān)聽客戶端的連接,這個(gè)工作是在server.c文件中的listenToPort函數(shù)中完成的:
static int listenToPort(int port, int *fds, int *countptr) {
int j;
int s;
int count = 0;
/* ...... */
/* 創(chuàng)建監(jiān)聽Socket */
s = anetTcpServer(server.neterr, port, server.bindaddr);
/* ...... */
/* 監(jiān)聽Socket并將Socket存放在fds中 */
fds[count++] = s;
if (server.ipfd_count == 0) server.ipfd = s;
server.ipfd_count++;
return count;
}
在有新的連接請求時(shí),Redis會(huì)調(diào)用accept函數(shù)接收客戶端的連接,并創(chuàng)建一個(gè)新的Socket套接字來處理這個(gè)新連接。在server.c文件的acceptTcpHandler函數(shù)中,有關(guān)于新連接的處理:
static void acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
/* ...... */
/* 接收新連接 */
cfd = anetTcpAccept(server.neterr, fd, cip, &cport);
/* ...... */
/* 將新連接加入到Epoll或Select事件監(jiān)聽中 */
if (aeCreateFileEvent(server.el, cfd, AE_READABLE, readQueryFromClient, c) == AE_ERR) {
close(cfd);
return;
}
/* ...... */
}
在上面的代碼中可以看到,Redis將新連接注冊到了Event Loop中,當(dāng)有讀事件時(shí),即可回調(diào)readQueryFromClient函數(shù)處理讀取的數(shù)據(jù)。
Redis事件處理機(jī)制
在Redis中,Event Loop既是網(wǎng)絡(luò)處理的入口,也是Redis內(nèi)部事件的處理單元。Redis服務(wù)會(huì)注冊一些網(wǎng)絡(luò)事件,當(dāng)網(wǎng)絡(luò)事件觸發(fā)時(shí),會(huì)被傳入注冊的處理函數(shù)進(jìn)行執(zhí)行。Redis的事件處理流程可以用以下偽代碼表示:
while (server.running) {
/* 等待事件到來 */
aeProcessEvents(server.el, AE_ALL_EVENTS);
/* 調(diào)用處理事件的函數(shù) */
processEvents();
}
在Redis的主循環(huán)中,首先等待事件到來。當(dāng)事件觸發(fā)后,Redis通過Event Loop將該事件傳入對應(yīng)的處理函數(shù)進(jìn)行處理。不同的事件會(huì)傳給不同的處理函數(shù),例如網(wǎng)絡(luò)連接事件會(huì)被傳入acceptTcpHandler函數(shù)進(jìn)行處理,讀寫事件會(huì)被傳到readQueryFromClient 或 writeQueryToClient中,從而完成事件的處理。
Redis的網(wǎng)絡(luò)模型源碼解讀
下面我們來看一下Redis在網(wǎng)絡(luò)模型層的實(shí)現(xiàn)源碼,首先是select網(wǎng)絡(luò)模型的部分源碼。
在networking.c文件中,Redis采用了常規(guī)的select模型,可以選用epoll或kqueue來取代select:
#ifdef HAVE_EPOLL
aeCreateFileEvent = aeCreateFileEventEpoll;
... /* 省略部分代碼 */
#else
aeCreateFileEvent = aeCreateFileEventSelect;
... /* 省略部分代碼 */
#endif
Redis使用select這種方式來解決大量客戶端連接的問題,有效避免了網(wǎng)絡(luò)IO阻塞。
對于Redis適應(yīng)多個(gè)CP多核CPU架構(gòu)的設(shè)計(jì),Redis使用多線程,每個(gè)線程負(fù)責(zé)一個(gè)event loop,以此來完成對IO事件的處理。根據(jù)操作系統(tǒng)內(nèi)核的擴(kuò)展方式,Redis支持了多Reactor模型的實(shí)現(xiàn),在server.c文件中有如下代碼:
#ifndef USE_LIBEV
for (j = 0; j nused; j++) {
aeEventLoop *eventLoop = server.el->events[j].el;
/* 為每個(gè)event loop分配一個(gè)thread */
if (aeCreateTimeEvent(eventLoop, 1, server.cron, NULL, NULL) == AE_ERR) {
RedisLog(REDIS_WARNING,"Can't create event loop timers.");
exit(1);
}
if (aeCreateFileEvent(eventLoop,
eventLoop->apidata->threads[j].channel[0], AE_READABLE,
wakeThreadHandler, NULL) == AE_ERR) {
RedisLog(REDIS_WARNING,"Can't create wakeup pipe.");
exit(1);
}
}
#else
RedisLog(REDIS_WARNING,"Warning: libev selected but Redis built without it, reverting to multithreaded mode.");
#endif
在Redis啟動(dòng)時(shí),它會(huì)為每個(gè)Event Loop分配一個(gè)線程,并在每個(gè)Event Loop中創(chuàng)建一個(gè)事件計(jì)時(shí)器。在Redis啟動(dòng)后,當(dāng)有新客戶端連接請求時(shí),將會(huì)傳遞給不同的Event Loop中處理,每個(gè)Event Loop會(huì)擔(dān)任不同的事件觸發(fā)器來處理事件,避免單個(gè)Event Loop過載,導(dǎo)致性能下降。
Redis多路復(fù)用技術(shù)
Redis采用的多路復(fù)用技術(shù)有兩種:select和epoll/kqueue。不同的操作系統(tǒng)對于select的實(shí)現(xiàn)方式不同,Linux 2.6之前采用的是輪詢方式,Linux 2.6后采用了epoll/kqueue。
Redis通過多路復(fù)用技術(shù),將服務(wù)器事件集中在一起,針對每個(gè)客戶端Socket,在需要的時(shí)候發(fā)出相應(yīng)的事件。通過這種方式,Redis能夠較為高效地處理大量的并發(fā)請求,而不會(huì)因頻繁的IO操作而降低性能。
總結(jié)
通過本文的分析,我們可以了解到了Redis源碼的網(wǎng)絡(luò)實(shí)現(xiàn)原理以及事件處理機(jī)制。在實(shí)際開發(fā)中,我們應(yīng)該了解Redis的內(nèi)部實(shí)現(xiàn),掌握Redis的調(diào)優(yōu)技巧,以此提升系統(tǒng)性能和運(yùn)行穩(wěn)定性。
成都服務(wù)器托管選創(chuàng)新互聯(lián),先上架開通再付費(fèi)。
創(chuàng)新互聯(lián)(www.cdcxhl.com)專業(yè)-網(wǎng)站建設(shè),軟件開發(fā)老牌服務(wù)商!微信小程序開發(fā),APP開發(fā),網(wǎng)站制作,網(wǎng)站營銷推廣服務(wù)眾多企業(yè)。電話:028-86922220
文章名稱:研究Redis源碼網(wǎng)絡(luò)分析解讀(redis 源碼網(wǎng)絡(luò)分析)
新聞來源:http://fisionsoft.com.cn/article/dhipses.html


咨詢
建站咨詢
