帮助中心/最新通知

质量为本、客户为根、勇于拼搏、务实创新

< 返回文章列表

【服务器相关】Redis学习教程之命令的执行过程详解

发表时间:2025-09-24 16:09:00 小编:主机乐-Yutio

前言

之前写了一系列文章,已经很深入的探讨了 Redis 的数据结构,数据库的实现,key的过期策略以及 Redis 是怎么处理事件的。所以距离 Redis 的单机实现只差最后一步了,就是 Redis 是怎么处理 client 发来的命令并返回结果的,所以我们就仔细讨论一下 Redis 是怎么执行命令的。

阅读这篇文章你将会了解到:

  • Redis 是怎么执行远程客户端发来的命令的

Redis client(客户端)

Redis 是单线程应用,它是如何与多个客户端简历网络链接并处理命令的?
由于 Redis 是基于 I/O 多路复用技术,为了能够处理多个客户端的请求,Redis 在本地为每一个链接到 Redis 服务器的客户端创建了一个 redisClient 的数据结构,这个数据结构包含了每个客户端各自的状态和执行的命令。 Redis 服务器使用一个链表来维护多个 redisClient 数据结构。

在服务器端用一个链表来管理所有的 redisClient。

Redis Server (服务端)

上文是从 redisClient 的角度来观察命令的执行,文章接下来的部分将会从 Redis 的代码层面,微观的观察 Redis 是怎么实现命令的执行的。

redisServer 的启动

在了解redisServer 的工作机制的工作机制之前,需要了解 redisServer 的启动做了什么:

可以继续观察 Redis 的 main() 函数。

Redis 中的事件驱动模型》 我们讲解过,redis 使用不同的事件处理器,处理不同的事件。

在这段代码里面:

  • 初始化了事件处理器的 eventLoop
  • 向 eventLoop 中注册了两个事件处理器 acceptTcpHandler 和 acceptUnixHandler,分别处理远程的链接和本地链接。

redisClient 的创建

当有一个远程客户端连接到 Redis 的服务器,会触发 acceptTcpHandler 事件处理器.

acceptTcpHandler 事件处理器,会创建一个链接。然后继续调用 acceptCommonHandler。

acceptCommonHandler 事件处理器的作用是:

  • 调用 createClient() 方法创建 redisClient
  • 检查已经创建的 redisClient 是否超过 server 允许的数量的上限
  • 如果超过上限就拒绝远程连接
  • 否则创建 redisClient 创建成功
  • 并更新连接的统计次数,更新 redisClinet 的 flags 字段

这个时候 Redis 在服务端创建了 redisClient 数据结构,这个时候远程的客户端就在 redisServer 中创建了一个代理。远程的客户端就与 Redis 服务器建立了联系,就可以向服务器发送命令了。

处理命令

在 createClient() 行数中:


// 绑定读事件到事件 loop (开始接收命令请求)
if (aeCreateFileEvent(server.el,fd,AE_READABLE,readQueryFromClient, c) == AE_ERR)

向 eventLoop 中注册了 readQueryFromClient。 readQueryFromClient 的作用就是从client中读取客户端的查询缓冲区内容。

然后调用函数 processInputBuffer 来处理客户端的请求。在 processInputBuffer 中有几个核心函数:

  • processInlineBuffer 和 processMultibulkBuffer 解析 querybuf 中的命令,记录到 argc 和 argv 中。
  • processCommand 根据 argv[0] 查找对应的 recommen,执行 recommend 对应的执行函数。在执行之前还会验证命令的正确性。将结果存入 buf & bufpos & reply 中

返回数据

万事具备了,执行完了命令就需要把数据返回给远程的调用方。调用链如下

processCommand -> addReply -> prepareClientToWrite

在 prepareClientToWrite 中我们有见到了熟悉的代码:


aeCreateFileEvent(server.el, c->fd, AE_WRITABLE,sendReplyToClient, c) == AE_ERR) return REDIS_ERR;

向 eventloop 绑定了 sendReplyToClient 事件处理器。

在 sendReplyToClient 中观察代码发现,如果 bufpos 大于 0,将会把 buf 发送给远程的客户端,如果链表 reply 的长度大于0,就会将遍历链表 reply,发送给远程的客户端,这里需要注意的是,为了避免 reply 数据量过大,就会过度的占用资源引起 Redis 相应慢。为了解决这个问题,当写入的总数量大于 REDIS_MAX_WRITE_PER_EVENT 时,Redis 将会临时中断写入,记录操作的进度,将处理时间让给其他操作,剩余的内容等下次继续。这样的套路我们一路走来看过太多了。

总结

  1. 远程客户端连接到 redis 后,redis服务端会为远程客户端创建一个 redisClient 作为代理。
  2. redis 会读取嵌套字中的数据,写入 querybuf 中。
  3. 解析 querybuf 中的命令,记录到 argc 和 argv 中。
  4. 根据 argv[0] 查找对应的 recommand。
  5. 执行 recommend 对应的执行函数。
  6. 执行以后将结果存入 buf & bufpos & reply 中。
  7. 返回给调用方。返回数据的时候,会控制写入数据量的大小,如果过大会分成若干次。保证 redis 的相应时间。

Redis 作为单线程应用,一直贯彻的思想就是,每个步骤的执行都有一个上限(包括执行时间的上限或者文件尺寸的上限)一旦达到上限,就会记录下当前的执行进度,下次再执行。保证了 Redis 能够及时响应不发生阻塞。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。


联系我们
返回顶部