Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5644586
  • 博文数量: 291
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 7924
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-06 14:28
个人简介

阿里巴巴是个快乐的青年

文章分类

全部博文(291)

文章存档

2018年(21)

2017年(4)

2016年(5)

2015年(17)

2014年(68)

2013年(174)

2012年(2)

分类: 数据库开发技术

2012-08-31 19:05:57

Technorati 标签: ,

关于Redis资料:

    要看原滋原味的请点,要看有我参与的山寨货请点,当然我也不反对看。

    在接下来的日子里,我会记录下我对Redis源码的一些认识,首先从Event driven programming library开始,没有理由,如果有:那就是redis.h包含的非系统头文件从#include "ae.h"开始,本系列文章以版源码为基准,言归正传吧。


一、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属性设置

    anetTcpNoDelay:设置是否关闭Nagle算法,Nagle算法作用点。

    anetNonBlock:设置阻塞还是非阻塞。

    anetTcpKeepAlive:设置是否开启协议栈心跳,协议栈心跳作用点这里

    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))

    三者都有统一的接口,功能大体类似,但也有细节差别,以epoll(参看这里)为蓝本解析如下:

    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 NET流程图

    看图,不解释。

阅读(1360) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

scq2099yt2012-08-31 19:07:45

在CU的处女作