Hiredis
结构图
sds
说明 :简单字符类型,typedef char * sds
API
sds sdsnewlen(const void *init, size_t initlen)
sds sdsnew(const char *init)
sds sdsempty(void)
size_t sdslen(const sds s)
sds sdsdup(const sds s)
void sdsfree(sds s)
size_t sdsavail(const sds s)
sds sdsgrowzero(sds s, size_t len)
grow到至少只用了len长度,多出的被设置为zero
sds sdscatlen(sds s, const void *t, size_t len)
sds sdscat(sds s, const char *t)
sds sdscatsds(sds s, const sds t)
sds sdscpylen(sds s, const char *t, size_t len)
sds sdscpy(sds s, const char *t)
sds sdscatvprintf(sds s, const char *fmt, va_list ap)
sds sdscatprintf(sds s, const char *fmt, ...)
sds sdscatfmt(sds s, char const *fmt, ...)
sds sdstrim(sds s, const char *cset)
void sdsrange(sds s, int start, int end)
截取保留到指定区间
void sdsupdatelen(sds s)
使用strlen(s) 来更新使用的长度
void sdsclear(sds s)
int sdscmp(const sds s1, const sds s2)
sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count)
void sdsfreesplitres(sds *tokens, int count)
void sdstolower(sds s)
void sdstoupper(sds s)
sds sdsfromlonglong(long long value)
sds sdscatrepr(sds s, const char *p, size_t len)
sds *sdssplitargs(const char *line, int *argc)
sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen)
将s中的字符,根据from转化为to 比如 s 为 abc,from为 ac , to 为12,则转化后为1b2
sds sdsjoin(char **argv, int argc, char *sep)
将字符用sep 连接起来
sds sdsMakeRoomFor(sds s, size_t addlen)
保证s有充足的可以空间addlen
void sdsIncrLen(sds s, int incr)
将已使用的长度加上incr作为新的已经使用的长度,incr可以为负数,不会分配和释放空间
sds sdsRemoveFreeSpace(sds s)
释放free空间
size_t sdsAllocSize(sds s)
获取已经分配的大小
hiredis
redisReader
API
redisReader *redisReaderCreate(void)
创建redisReader,并初始化,初始化默认的对象创建函数组为defaultFunctions,初始化maxbuf为REDIS_READER_MAX_BUF(1024 * 16),maxbuf控制当redisReader buffer申请的大小大于maxbuf时,必要时会进行内存释放。
void redisReaderFree(redisReader *r)
释放redisReader。
int redisReaderFeed(redisReader *r, const char *buf, size_t len)
将字符流放入到redisReader 的buffer区域。
int redisReaderGetReply(redisReader *r, void **reply)
解析redisReader的buffer字符流,并获取到相应结果。
redisReaderGetReply 解析过程依赖于redisReadTask和redisReplyObjectFunctions函数组,其中redisReadTask主要用在处理Array对象,redisReplyObjectFunctions函数组用于创建对象。
outbuf
redisContext 结构体中的变量,作为命令的输出缓冲区,所有命令会写到这个缓冲区,当调用redisGetReply时,如果调用redisReaderGetReply未获取到应答对象,并且redisContext是阻塞模式时,会将该缓冲区的数据发送出去。主动调用redisBufferWrite也会发送。
redisConext
API
redisContext *redisConnect(const char *ip, int port)
redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv)
redisContext *redisConnectNonBlock(const char *ip, int port)
redisContext *redisConnectBindNonBlock(const char *ip, int port, const char *source_addr)
redisContext *redisConnectUnix(const char *path)
redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv)
redisContext *redisConnectUnixNonBlock(const char *path)
redisContext *redisConnectFd(int fd)
int redisSetTimeout(redisContext *c, const struct timeval tv)
int redisEnableKeepAlive(redisContext *c)
void redisFree(redisContext *c)
int redisFreeKeepFd(redisContext *c)
int redisBufferRead(redisContext *c)
读取数据流,写入到redisReader缓冲区。
int redisBufferWrite(redisContext *c, int *done)
将outbuf缓冲区数据,发送出去
int redisGetReplyFromReader(redisContext *c, void **reply)
调用redisReaderGetReply,也就是说使用redisReader的API取获取应答。
int redisGetReply(redisContext *c, void **reply)
使用redisGetReplyFromReader获取应答,如果没有应答,将outbuf缓冲区发送出去,然后循环使用redisBufferRead,读取数据流,使用redisGetReplyFromReader启尝试获取应答,直到获取到应答信息。
int redisFormatCommand(char **target, const char *format, ...)
格式化命令
int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len)
将已经格式化的命令添加的outbuf发送缓冲区当中
int redisAppendCommand(redisContext *c, const char *format, ...)
格式化命令,并将命令添加到outbuf 发送缓冲区当中。
void *redisCommand(redisContext *c, const char *format, ...)
格式化命令,并将命令添加到outubuf发送缓冲区中(调用 redisAppendCommand),如果是block模式的话,调用redisGetReply 获取应答。
net
API
int redisCheckSocketError(redisContext *c);
int redisContextSetTimeout(redisContext *c, const struct timeval tv);
说明:设置redisContext 上下文关联的socket描述符的发送超时时间和接收超时时间
int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct ti meval *timeout);
int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout, const char *source_addr);
int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *ti meout);
int redisKeepAlive(redisContext *c, int interval);
说明:keepalive原理:TCP内嵌有心跳包,以服务端为例,当server检测到超过一定时间(/proc/sys/net/ipv4/tcp_keepalive_time 7200 即2小时)没有数据传输,那么会向client端发送一个keepalive packet,此时client端有三种反应:
1、client端连接正常,返回一个ACK.server端收到ACK后重置计时器,在2小时后在发送探测.如果2小时内连接上有数据传输,那么在该时间的基础上向后推延2小时发送探测包;
2、客户端异常关闭,或网络断开。client无响应,server收不到ACK,在一定时间(/proc/sys/net/ipv4/tcp_keepalive_intvl 75 即75秒)后重发keepalive packet, 并且重发一定次数(/proc/sys/net/ipv4/tcp_keepalive_probes 9 即9次);
3、客户端曾经崩溃,但已经重启.server收到的探测响应是一个复位,server端终止连接。
这个函数是启动c关联的socket套接字的keepalive,设置情况2重发的时间间隔,重发次数,以及下一次发送探测包的时间间隔
adapters
实现的接口规范
如:int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac)
将async层的redisAsyncContext 与 ae事件处理相关联起来。
1、 需要实现redisAeAttach函数设置ac->ev结构体中的读写事件注册删除函数。
如图:
2、需要将实现读事件回调函数,并且该读事件回调函数调用async层的redisAsyncHandleRead函数
如图:
3、需要将实现写事件回调函数并调用async层的redisAsyncHandleWrite函数
如图:
使用RedisAeEvent 结构体将async 与 ae 联通起来,注册事件是,RedisAeEvenet变量传入,回调函数时,将该变量传回。
async
异步上下文
struct redisAsyncContext
结构体成员
redisContext c; redisContext 上下文用于与redis服务器通讯
int err; 错误码
char * errstr; 错误信息
struct {
void * data;
void (*addRead)(void *privdata);
void (*delRead)(void * privdata);
void (*addWrite)(void * privdata);
void (*delWrite)(void *) privdata);
void (*cleanup)(void *)privdata):
} ev; 事件数据钩子
redisDisconnectCallback *onDisconnect; 回调函数,当连接被断开时调用
redisConnectCallback *onConnect; 回调函数,当第一个写事件接收到时调用
redisCallbackList replies;
struct {
redisCallbackList invaild;
struct dict * channels;
struct dict * patterns;
} pub; 订阅回调函数
API
redisAsyncContext *redisAsyncConnect(const char *ip, int port)
说明:代理hiredis redisConnectNonBlock函数,hihredisConnectNonBlock 函数连接服务器后,设置socket为非阻塞状态
redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr)
说明:代理redisConnectBindNonBlock 函数,redisConnectBindNonBlock函数连接服务器后,设置socket为非阻塞状态
redisAsyncContext *redisAsyncConnectUnix(const char *path)
说明:代理redisConnectUnixNonBlock函数,redisConnectUnixNonBlock函数连接服务器后,设置socket为非阻塞状态
int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn)
说明:设置连接回调函数
int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn)
说明:设置断开连接回调函数
void redisAsyncDisconnect(redisAsyncContext *ac)
void redisAsyncFree(redisAsyncContext *ac)
void redisAsyncHandleRead(redisAsyncContext *ac)
读事件回调函数,适配器层实现的读事件回调函数需要调用该函数
void redisAsyncHandleWrite(redisAsyncContext *ac)
写事件回调函数,适配器层实现的写事件回调函数需要调用该函数
int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...)
异步发送命令到Redis服务,有应答调用fn回调函数。
异步处理流程