關于Redis資料:
在接下來的日子裡,我會記錄下我對Redis源碼的一些認識,首先從Event driven programming library開始,沒有理由,如果有:那就是redis.h包含的非系統頭檔案從#include
一、NET分層
Redis 網絡部分主要分四層:

圖1 NET分層圖
1、 TCP/Unix Socket層(Anet.h(117)、Anet.c(405))
(1)socket建立
anetCreateSocket:建立TCP/Unix
socket,設定socket SO_REUSEADDR。
(2)socket屬性設定
anetNonBlock:設定阻塞還是非阻塞。
anetSetSendBuffer:設定發送buffer大小。
(3)Connect
anetTcpGenericConnect:TCP Connect原始接口封裝,輸入IP位址和阻塞/非阻塞參數。
anetTcpConnect:TCP阻塞連接配接。
anetTcpNonBlockConnect:TCP非阻塞連接配接。
anetUnixGenericConnect:Unix Connect原始接口封裝,輸入IP位址和阻塞/非阻塞參數。
anetUnixConnect:Unix阻塞連接配接。
anetUnixNonBlockConnect:Unix非阻塞連接配接。
(4)Listen
anetListen:bind和listen(511原因請查Nginx)封裝。
anetTcpServer:調用anetCreateSocket和anetListen監聽連接配接到來。
anetUnixServer:調用anetCreateSocket和anetListen監聽連接配接到來。
(5)Accept
anetGenericAccept:accept封裝,while直到accept成功或失敗才傳回。
anetTcpAccept:調用anetGenericAccept,傳回fd,帶回IP和Port(函數參數)或錯誤。
anetUnixAccept:調用anetGenericAccept,傳回fd,或帶回錯誤(函數參數)。
(6)IP和host互轉
anetPeerToString:由IPAddress->Host。
anetResolve:由Host->IPAddresss。
(7)格式化error
anetSetError:變長參數格式化,函數參數帶回格式化後error資訊。
2、 I/O模型層(Ae_select.c(72)、Ae_epoll.c(101)、Ae_kqueue.c(105))
aeApiState:包含epoll fd句柄和Event指針的struct,epoll和kqueue基本一緻,而select是rfds和wfds集合及副本,具體見Ae_select.c代碼第7~12行。
aeApiCreate:建立aeApiState,并以此初始化aeEventLoop(作用見後文)。epoll_create參數采用Linux kernel的hint值1024。
aeApiFree:close epoll fd句柄,釋放malloc的aeApiState和aeEventLoop。
aeApiAddEvent:通過mask修改或者添加fd對應Event的EPOLLIN或EPOLLOUT(epoll_ctl)。
aeApiDelEvent:通過mask修改或者删除fd對應Event的EPOLLIN或EPOLLOUT(epoll_ctl)。
aeApiPoll:epoll_wait等待核心傳回事件集合,填寫fire事件集合用于回調AE_READABLE和AE_WRITABLE對應函數。
aeApiName:取得I/O模型字元串名稱("select"、"epoll"、"kqueue")。
3、 EventLoop層(Ae.h(117)、Ae.c(405))
(1)回調函數指針
typedef void aeFileProc(struct aeEventLoop
*eventLoop, int fd, void *clientData, int mask);
typedef int aeTimeProc(struct aeEventLoop
*eventLoop, long long id, void *clientData);
typedef void aeEventFinalizerProc(struct
aeEventLoop *eventLoop, void *clientData);
typedef void aeBeforeSleepProc(struct
aeEventLoop *eventLoop);
(2)Event Struct
aeFileEvent:讀寫事件回調。
aeTimeEvent:定時器事件回調。
aeFiredEvent:觸發事件回調。
aeEventLoop:主事件,包含讀寫事件、定時器事件、觸發事件清單。
(3)Event接口API
aeCreateEventLoop:建立EventLoop。
aeDeleteEventLoop:删除EventLoop。
aeStop:置EventLoop stop标志。
aeCreateFileEvent:添加關注事件。
aeDeleteFileEvent:删除關注事件。
aeGetFileEvents:擷取事件mask
aeGetTime:擷取目前時間。
aeAddMillisecondsToNow:增加毫秒數目前時間的秒和毫秒上。
aeCreateTimeEvent:添加定時器事件。
aeDeleteTimeEvent:删除定時器事件。
SearchNearestTimer:搜尋最近的定時器。
processTimeEvents:處理定時器事件,回調函數傳回AE_NOMORE(-1)則删除定時器,否則更新定時器時間為回調函數傳回的時間。
aeProcessEvents:處理各種事件,用最近定時器即将到來的時間作為epoll_wait的逾時間,非常巧妙,如果馬上到就立即傳回,否則逾時間到再傳回。
aeMain:主main,while循環直到eventLoop->stop不為0,在調用aeProcessEvents前,先回調aeBeforeSleepProc。
aeGetApiName:擷取I/O模型字元串名稱("select"、"epoll"、"kqueue")。
aeSetBeforeSleepProc:設定aeBeforeSleepProc回調函數。
4、 Networking層(Networking.c(1334))
暫不表與網絡層無直接關系的接口函數。
createClient:建立redisClient,有連接配接則設定fd為nonblocking,設定TCP_NODELAY,設定AE_READABLE對應的回調函數readQueryFromClient。
prepareClientToWrite:在發送資料給用戶端時的預處理,即可以發送資料時設定AE_WRITABLE對應的回調函數sendReplyToClient;是REDIS_LUA_CLIENT時傳回REDIS_OK;是fake client或者slave或者setup write handler failed時傳回REDIS_ERR。
acceptCommonHandler:調用createClient,校驗是否達到最大用戶端數。
acceptTcpHandler:針對TCP依次調用anetTcpAccept、acceptCommonHandler。
acceptUnixHandler:針對Unix,作用同acceptTcpHandler。
freeClient:釋放redisClient,删除AE_READABLE、AE_WRITABLE,斷開master/slave,清除MULTI/EXEC
state等。
sendReplyToClient:發送資料的回調函數,處理write邏輯。
readQueryFromClient:接收資料的回調函數,處理read邏輯。
還有一大票addReply…和get…,在此略去。
二、NET流程
以redis-cli 從redis-server get資料為例來描述整體流程。
圖2 流程圖
打完收工,
。。。