• 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源码

  • 相关阅读:
    L958. 二叉树的完全性检验 java
    华为云发布拉美互联网战略,携手客户与伙伴迈向云原生2.0新时代
    世界杯竞猜项目Dapp-第一章(合约开发)
    .NetCore+Vue2.0前后端分离的个人博客项目
    【开源项目】个人如何在开源社区中成长?
    云服务器部署k8s集群
    什么是JUC
    排序之快速排序
    【PB续命01】Microsoft.XMLHttp的属性和方法的简介及使用
    一图带你了解封装与分用
  • 原文地址:https://blog.csdn.net/qq_43196360/article/details/127524853