redis客户端连接到服务器的步骤

5 篇文章 0 订阅

看了大约3天的redis-cli了,是进行总结的时候了。

和大多数客户端连接到服务器一样,redis-cli连接到服务器也主要分为两个阶段,请求连接阶段和数据传送阶段。具体来讲redis-cli做的事情有:

1、以socket方式建立连接;

2,选择相应的数据库;

3,对客户端发送的命令进行编码;

4,发送客户端编码的数据(write);

5,接收服务器回应的数据(read);

6,解析接收的数据。

以下根据源码对客户端所做的事情进行分析。

    /* Start interactive mode when no command is provided */
    if (argc == 0 && !config.eval) {
        /* Ignore SIGPIPE in interactive mode to force a reconnect */
        signal(SIGPIPE, SIG_IGN);

        /* Note that in repl mode we don't abort on connection error.
         * A new attempt will be performed for every command send. */
        cliConnect(0);
        repl();
    }

以上代码为redis-cli主函数中关于交互模式的部分,主要由cliConnect和repl构成,其中前者负责连接服务器,后者负责进行数据传输。

建立连接

关于客户端与服务器建立连接,我们知道主要的步骤分为、

1,创建socket(有一套固定的模式);

2,根据设定的ip及端口号,与服务器进行connet;

好的,这本来就是传统的做法,咱们看看redis它怎么做了呢?

它首先出定义了一个redis上下文结构,包含一次请求及回应的数据信息以及状态信息如下:

typedef struct redisContext {
    int err;
    char errstr[128]; 
    int fd;
    int flags;
    char *obuf;
    redisReader *reader; 
    enum redisConnectionType connection_type;
    struct timeval *timeout;
    struct {
        char *host;
        char *source_addr;
        int port;
    } tcp;

    struct {
        char *path;
    } unix_sock;
} redisContext;

err、errstr为接收数据不正常时定义的变量,fd为客户端创建的sockfd,obuf为客户端的编码命令,reader为服务器返回的数据。并且要通过cliConnect进行初始化,定义tcp,fd等信息。

先看看cliConnect的操作

* Connect to the server. It is possible to pass certain flags to the function:
 *      CC_FORCE: The connection is performed even if there is already
 *                a connected socket.
 *      CC_QUIET: Don't print errors if connection fails. */
static int cliConnect(int flags) {
    if (context == NULL || flags & CC_FORCE) {
        if (context != NULL) {
            redisFree(context);
        }

        if (config.hostsocket == NULL) {
            context = redisConnect(config.hostip,config.hostport);
        } else {
            context = redisConnectUnix(config.hostsocket);
        }
        ...
   
        anetKeepAlive(NULL, context->fd, REDIS_CLI_KEEPALIVE_INTERVAL);

        /* Do AUTH and select the right DB. */
        if (cliAuth() != REDIS_OK)
            return REDIS_ERR;
        if (cliSelect() != REDIS_OK)
            return REDIS_ERR;
    }
    return REDIS_OK;
}

flags用于表示客户端在已经连接到了服务器的情况下,是否还能在连接,0表示不允许连接,1表示允许连接(在改变客户端登录的服务器时会用到)。

redisConnect定义了context的ip,port;调用redisContextInit初始化字符串,调用redisContextConnectTcp(c,ip,port,NULL)完成了socket连接。

由于已经连接完成,cliSelect调用命令

 reply = redisCommand(context,"SELECT %d",config.dbnum);

选0号数据库(默认)。

数据传输

在repl()中,使用了linenoise工具处理输入的行,字符串分割部分采用了cliSplitArgs,参数处理部分采用issueCommandRepeat。它调用redisAppendCommandArgv将参数编码,传递给context的obu;调用cliReadReply负责解码客户端接收到的数据;调用redisGetReply(在cliReadReply中)负责底层I/O数据的传输。

int redisGetReply(redisContext *c, void **reply) {
    int wdone = 0; 
    void *aux = NULL;

    /* Try to read pending replies */
    if (redisGetReplyFromReader(c,&aux) == REDIS_ERR)
        return REDIS_ERR;

    /* For the blocking context, flush output buffer and read reply */
    if (aux == NULL && c->flags & REDIS_BLOCK) {
        /* Write until done */
        do {
            if (redisBufferWrite(c,&wdone) == REDIS_ERR)
                return REDIS_ERR;
        } while (!wdone);

        /* Read until there is a reply */
        do {
            if (redisBufferRead(c) == REDIS_ERR)
                return REDIS_ERR;
            if (redisGetReplyFromReader(c,&aux) == REDIS_ERR)
                return REDIS_ERR;
        } while (aux == NULL);
    }

    /* Set reply object */
    if (reply != NULL) *reply = aux;
    return REDIS_OK;
}

主要是redisBufferWrite和redisBufferRead,分别向I/Obuf中写入和读取数据。redisGetReplyFromReader负责解码接收数据。

总结:

1,redis-cli在基本的客户端编程的基础上,增加了Context定义,可以知道数据的类型,数据的好坏。

2,增加了编码解码功能,一般编码解码功能可以使数据更安全,不知是不是因为这样才进行编码解码。

3,具体的实现部分还是需要进一步学习。

 

ps:一对小情侣座我对面,真是腻歪。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Redis的工作流程可以概括为以下几个步骤: 1. 客户端Redis服务器建立连接客户端通过网络与Redis服务器建立连接,可以使用一些客户端工具或者编程语言的Redis库来进行连接。 2. 客户端发送命令:客户端Redis服务器发送命令,命令可以是读取数据、写入数据或执行其他操作的指令。命令由多个参数组成,例如GET key,SET key value等。 3. Redis服务器接收命令:Redis服务器接收到客户端发送的命令后,进行解析。它会解析命令类型、参数和选项等信息,以确定需要执行的操作。 4. 执行命令:根据命令的类型和参数,Redis服务器会执行相应的操作。如果是读取操作,它会查询相应的键值对并返回结果;如果是写入操作,它会将数据写入内存中指定的键;其他操作也会根据命令执行相应的逻辑。 5. 响应返回:Redis服务器执行完命令后,将执行结果封装成响应消息,并发送给客户端。响应消息可以包含请求的数据或者一个简单的确认消息。 6. 客户端处理响应:客户端接收到Redis服务器发送的响应后,进行处理。根据响应的内容,客户端可以提取所需的数据或者根据响应执行进一步的操作。 在整个过程中,Redis使用的是基于TCP的协议与客户端进行通信。客户端通过发送命令到Redis服务器连接来与服务器进行交互,而服务器则根据命令执行相应的操作,并将结果返回给客户端。同时,Redis通过自己的内存管理器来管理键值对存储在内存中的方式,并提供持久化机制将数据写入磁盘以防止数据丢失。 需要注意的是,Redis是单线程的,即每个命令在执行时会阻塞其他命令的执行。这主要是因为Redis的内存访问速度非常快,单线程可以避免多线程之间的竞争和同步开销,从而提高性能。但是,Redis通过使用非阻塞I/O和事件驱动模型,可以同时处理多个客户端请求,以实现高并发处理能力。此外,Redis还提供了主从复制和哨兵等机制来提高系统的可用性和容错性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值