Redis源码解析:19Hiredis异步API代码解析

本文深入解析Hiredis的异步API,包括TCP建链、发送命令和断链过程。介绍了异步上下文结构、回调函数设置以及与事件库的交互。异步API在命令发送时会自动管道化,使用回调函数处理响应。重点讲解了建链的`redisAsyncConnect`、发送命令的`redisAsyncCommand`和断链的`redisAsyncDisconnect`函数的工作原理。
摘要由CSDN通过智能技术生成

         Hiredis中的异步API函数需要与事件库(libevent,libev, ev)一起工作。因为事件循环的机制,异步环境中的命令是自动管道化的。因为命令是异步发送的,因此发送命令时,必要情况下,需要提供一个回调函数,以便在收到命令回复时调用该函数。

         异步API涉及到的函数分别是:

redisAsyncContext *redisAsyncConnect(const char *ip, int port);
int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...);
int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen);
void redisAsyncDisconnect(redisAsyncContext *ac);

         以上函数分别对应TCP建链、发送命令和TCP断链。

 

一:异步上下文

         类似于同步操作API,异步操作API中也有一个上下文结构redisAsyncContext,用于维护异步链接中的各种状态。

         redisAsyncContext结构在同步上下文结构redisContext的基础上,增加了一些异步属性,它的定义如下:

typedef struct redisAsyncContext {
    /* Hold the regular context, so it can be realloc'ed. */
    redisContext c;

    /* Setup error flags so they can be used directly. */
    int err;
    char *errstr;

    /* Not used by hiredis */
    void *data;

    /* Event library data and hooks */
    struct {
        void *data;

        /* Hooks that are called when the library expects to start
         * reading/writing. These functions should be idempotent. */
        void (*addRead)(void *privdata);
        void (*delRead)(void *privdata);
        void (*addWrite)(void *privdata);
        void (*delWrite)(void *privdata);
        void (*cleanup)(void *privdata);
    } ev;

    /* Called when either the connection is terminated due to an error or per
     * user request. The status is set accordingly (REDIS_OK, REDIS_ERR). */
    redisDisconnectCallback *onDisconnect;

    /* Called when the first write event was received. */
    redisConnectCallback *onConnect;

    /* Regular command callbacks */
    redisCallbackList replies;

    /* Subscription callbacks */
    struct {
        redisCallbackList invalid;
        struct dict *channels;
        struct dict *patterns;
    } sub;
} redisAsyncContext;

         该结构的第一个属性就是同步上下文结构redisContext c,剩下的就是一些异步属性:

         结构体ev中包含了,当Hiredis异步API与事件库(libev,libevent, Redis ev)一起工作时,用于注册和删除读写事件的函数;

         回调函数onDisconnect,表示断链时会调用的函数,该属性可以通过redisAsyncSetDisconnectCallback函数设置;

         回调函数onConnect,表示TCP建链成功或失败之后会调用的函数,该属性可以通过redisAsyncSetConnectCallback函数设置;

         replies属性是一个redisCallbackList结构,也就是由回调结构redisCallback组成的单链表。当发送普通命令时,会依次将该命令对应的回调结构追加到链表中,当Redis服务器回复普通命令时,会依次调用该链表中的每个redisCallback结构中的回调函数;

         结构体sub用于处理订阅模式,其中的字典channels,以频道名为key,以回调结构redisCallback为value。当客户端使用Hiredis异步API发送”subscribe”命令后,服务器产生回复时,就会根据回复信息中的频道名查询字典channels,找到对应的回调结构,调用其中的回调函数。字典patterns与channels类似,只不过它用于”psubscirbe”命令,其中的key是频道名模式;回调链表invalid,当客户端处于订阅模式下,服务器发来了意想不到的回复时,会依次调用该链表中,每个回调结构中的回调函数。

 

二:建链

         函数redisAsyncConnect执行异步操作中的TCP建链。

redisAsyncContext *redisAsyncConnect(const char *ip, int port) {
    redisContext *c;
    redisAsyncContext *ac;

    c = redisConnectNonBlock(ip,port);
    if (c == NULL)
        return NULL;

    ac = redisAsyncInitialize(c);
    if (ac == NULL) {
        redisFree(c);
        return NULL;
    }

    __redisAsyncCopyError(ac);
    return ac;
}

         该函数首先根据ip和port,调用redisConnectNonBlock函数向Redis服务器发起非阻塞的建链操作,然后调用redisAsyncInitialize函数创建异步上下文结构redisAsyncContext。

 

         redisAsyncSetConnectCallback函数用于设置异步上下文中的建链回调函数。其代码如下:

int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn) {
    if (ac->onConnect == NULL) {
        ac->onConnect = fn;

        /* The common way to detect an established connection is to wait for
         * the first write event to be fired. This assumes the related event
         * library functions are already set. */
        _EL_ADD_WRITE(ac);
        return REDIS_OK;
    }
    return REDIS_ERR;
}

         该函数中,如果之前已经设置过建链回调函数了,则直接返回REDIS_ERR。

         该函数除了设置异步上下文中的建链回调函数之外,还会调用_EL_ADD_WRITE,注册可写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值