• REDIS篇(4)——命令执行过程(readQueryFromClient)


    前面讲过,ae循环在收到客户端请求时,会调用请求处理器——acceptTcpHandler ,而请求处理器会创建新的套接字并监听和绑定命令处理器——readQueryFromClient。本篇着重分析命令的执行过程。

    大概可分为:

    1、读取并分析套接口中协议格式的命令请求,设置redisClient的queryBuf、argv和argc属性------(processInlineBuffer)

    2、执行命令------(processCommand)

    1. 查找对应的命令实现
    2. 执行预备操作
    3. 执行命令及执行完的后续操作

    3、将命令回复发送给客户端------(sendReplyToClient)


    源码分析:

    首先一路跟踪readQueryFromClient函数来到processInputBuffer。这里主要看processInlineBufferprocessCommand分别对应上面的1、2两点
    在这里插入图片描述

    1、读取并分析套接口中协议格式的命令请求,设置redisClient的argv和argc属性(processInlineBuffer)
    在这里插入图片描述
    2、执行命令(processCommand)
    在这里插入图片描述
    上面除了lookupCommand(匹配命令实现函数)外,其他的大都是命令执行前的预备操作,而真正执行命令的地方在call方法

    call:
    在这里插入图片描述
    其中c->cmd->proc©这一行即执行了对应的命令实现函数。后面的则是执行命令的后续操作(但不包括返回给客户端的操作)

    3、将命令回复发送给客户端
    跟踪完readQueryFromClient会发现并没有看到有回复执行结果给客户端的代码。
    那么redis是如何将执行结果回复给客户端的呢?
    以set命令为例,点开setCommand可以看到addReply方法
    在这里插入图片描述
    不点进去看的同学可能会以为这里就是回复了。但其实不然,这里只是将当前客户端加入了server.clients_pending_write,并且将执行结果存到bufpos缓存区而已,并没有真正的回复。。。
    代码看到这里,一次事件处理就已经看完了。

    但是还是没有回复客户端啊???究竟是如何回复的?
    答案在aeMain(redis事件处理循环)
    前面讲过,除了将执行结果存到缓存区外,还会将当前客户端加入server.clients_pending_write。而在aeMain每次处理事件之前会先执行beforesleep方法
    在这里插入图片描述
    而beforeSleep会执行handleClientsWithPendingWrites(处理缓存区里的写数据)
    在这里插入图片描述
    handleClientsWithPendingWrites方法会先尝试执行writeToClient直接回复。若不行,再执行aeCreateFileEvent创建一个文件写事件并绑定回复处理器sendReplyToClient加入事件循环,由后面的事件循环再调用。
    在这里插入图片描述
    总的来说回复流程如下:
    在这里插入图片描述


    时序图分析:

    连接请求时序图:
    在这里插入图片描述

    命令请求时序图:
    在这里插入图片描述

    命令回复时序图:
    在这里插入图片描述

    参考文献:《Redis设计与实现》黄健宏著、redis-5.0.14源码

  • 相关阅读:
    root用户自动安装mysql 5.7脚本
    centos防火墙firewall-cmd限定特定的ip访问
    力扣第300题 最长递增子序列 c++ 动态规划题 附Java代码
    KY34 Is It A Tree?
    面向对象(三):常用知识下
    matlab abel变换图片处理
    详解:进程程序替换
    Linux网络基础2之http
    2023年中国泌尿内窥镜市场规模、竞争格局及细分产品规模分析[图]
    Nginx部署前端网页,Nginx搭建静态资源服务器
  • 原文地址:https://blog.csdn.net/qq_43196360/article/details/127524853