Redis 命令执行过程(下)

  • 时间:
  • 浏览:0
  • 来源:uu直播快3平台_UU快3直播官方

在 《Redis 事件机制详解》

一文中一点人知道,Redis 在两次事件循环之间会调用 beforeSleep 法子 出理 一点事情,而对 clients_pending_write 列表的出理 就在其中。

那我的好处是对于返回数据较少的客户端,不需用麻烦的注册写数据事件,守候事件触发再写数据到 socket,只是我在下一次事件循环周期就直接将数据写到 socket中,加快了数据返回的响应下行速率 。

setCommand 会判断set命令与否携带了nx、xx、ex机会px等可选参数,或者我 调用setGenericCommand命令。一点人直接来看 setGenericCommand 法子 。

handleClientsWithPendingWrites 法子 会遍历 clients_pending_write 列表,对于每个 client 都是先调用 writeToClient 法子 来尝试将返回数据从输出缓存区写入到 socekt中,机会还未写完,则都可以不都可以 调用 aeCreateFileEvent 法子 来注册那我写数据事件出理 器 sendReplyToClient,守候 Redis 事件机制的再次调用。

前文讲到 processCommand 法子 会从输入缓冲区中解溶于 对应的 redisCommand,或者我 调用 call 法子 执行解溶于 来的 redisCommand的 proc 法子 。不同命令的的 proc 法子 是不同的,比如说名为 set 的 redisCommand 的 proc 是 setCommand 法子 ,而 get 的则是 getCommand 法子 。通过四种 生活形式,实际上实现在Java 带有点痛 常见的多态策略。

每每本人博客地址,欢迎查看

在所有的 redisCommand 执行的最后,一般都是调用 addReply 法子 进行结果返回,一点人的分析也来到了 Redis 命令执行的返回数据阶段。

getGenericCommand 法子 会调用 lookupKeyReadOrReply 来从 dict 数据哈希表中查找对应的 key值。机会找都可以 ,则直接返回 C_OK;机会找到了,则根据值的类型,调用 addReply 机会 addReplyBulk 法子 将值打上去到输出缓冲区中。

里边只是我响应内容写入输出缓冲区的过程,下面看一下将数据从输出缓冲区写入 socket 的过程。

prepareClientToWrite 首先判断了当前 client与否需用返回数据:

在上一篇文章中《Redis 命令执行过程(上)》中,一点人首先了解 Redis 命令执行的整体流程,或者我 细致分析了从 Redis 启动到建立 socket 连接,再到读取 socket 数据到输入缓冲区,解析命令,执行命令等过程的原理和实现细节。接下来,一点人来具体看一下 set 和 get 命令的实现细节和如何将命令结果通过输出缓冲区和 socket 发送给 Redis 客户端。

sendReplyToClient 法子 虽然也会调用 writeToClient 法子 ,该法子 只是我将输出缓冲区中的 buf 和 reply 列表中的数据都尽机会多的写入到对应的 socket中。

addReply 法子 做了两件事情:

lookupKey 法子 则是通过 dictFind 法子 从 redisDb 的 dict 哈希表中查找键值,机会能找到,则根据 redis 的 maxmemory_policy 策略来判断是更新 lru 的最近访问时间,还是调用 updateFU 法子 更新一点指标,那些指标都需用在后续内存不足时对键值进行回收。

在判断键释放过期的逻辑带有那我特殊情况表:

固定buffer和响应链表,整体上构成了那我队列。那末 组织的好处是,既都需用节省内存,不需一开使英文预先分配大块内存,或者我 都需用出理 频繁分配、回收内存。

setGenericCommand 法子 的出理 逻辑如下所示:

Redis 将存储守候返回的响应数据的空间,也只是我输出缓冲区分成两每项,那我固定大小的 buffer 和那我响应内容数据的链表。在链表为空或者我 buffer 有足够空间时,则将响应打上去到 buffer 中。机会 buffer 满了则创建那我节点追加到链表上。_addReplyToBuffer 和 _addReplyObjectToList 只是我分别向这那我空间写数据的法子 。

beforeSleep 函数会调用 handleClientsWithPendingWrites 函数来出理 clients_pending_write 列表。

lookupKeyReadWithFlags 会从 redisDb 中查找对应的键值对,它首先会调用 expireIfNeeded判断键与否过期或者我 需用删除,机会为过期,则调用 lookupKey 法子 从 dict 哈希表中查找并返回。具体解释都需用看代码中的删剪注释

接着机会四种 生活 client 还未趋于稳定延迟守候写入 (CLIENT_PENDING_WRITE)的情况表,则将其设置为该情况表,并将其加入到 Redis 的守候写入返回值客户端队列中,也只是我 clients_pending_write队列。

或者我 从这里也会发现,机会 clients_pending_write 队列过长,则出理 时间也会之后,阻塞正常的事件响应出理 ,意味 Redis 后续命令延时增加。

Redis 在调用查找键值系列法子 前都是先调用 expireIfNeeded 来判断键与否过期,或者我 根据 Redis 与否配置了懒删除来进行同步删除机会异步删除。关于键删除的细节都需用查看《详解 Redis 内存管理机制和实现》一文。

接下来看 getCommand 的具体实现,同样的,它底层会调用 getGenericCommand 法子 。

具体 setKey 和 setExpire 的法子 实现一点人这里就不细讲,虽然只是我将键值打上去到db的 dict 数据哈希表中,将键和过期时间打上去到 expires 哈希表中,如下图所示。

prepareClientToWrite 函数,将客户端加入到了Redis 的守候写入返回值客户端队列中,也只是我 clients_pending_write 队列。请求出理 的事件出理 逻辑就开使英文了,守候 Redis 下一次事件循环出理 时,将响应从输出缓冲区写入到 socket 中。

下面的 aeMain 法子 只是我 Redis 事件循环的主逻辑,都需用看多每次循环时都是调用 beforesleep 法子 。