Redis(136)Redis的客户端缓存是如何实现的?

作者:Victor356日期:2025/11/21

Redis 的客户端缓存(Client-Side Caching)是一项重要特性,允许客户端在本地缓存 Redis 数据,从而减少与 Redis 服务器的通信频率,提高应用的响应速度和可扩展性。Redis 客户端缓存的实现主要依赖于以下几个核心组件和机制:

  1. 订阅机制:客户端通过订阅特定的键空间事件,获取键的变更通知。
  2. 通知机制:Redis 服务器在键发生变更时,通过发布/订阅(Pub/Sub)机制将变更通知推送给客户端。
  3. 缓存一致性:确保客户端缓存与 Redis 服务器的数据一致性。

核心概念和数据结构

1. 客户端缓存模式

Redis 提供了两种客户端缓存模式:

  • 主动推模式(Tracking Mode):服务器主动向客户端推送键的变更通知。
  • 被动拉模式(Polling Mode):客户端定期从服务器拉取键的变更信息。

2. 客户端状态

每个客户端的状态通过 client 结构体维护,其中包含缓存相关的信息:

1typedef struct client {
2    // ...
3    uint64_t client_tracking_redirection; /* Redirected ID for tracking invalidation messages */
4    uint64_t client_tracking_locks; /* Number of tracking locks */
5    uint8_t client_tracking_prefixes; /* Number of tracking prefixes */
6    // ...
7} client;
8

启用客户端缓存

客户端缓存可以通过 CLIENT CACHING 命令启用和配置。

1redis> CLIENT CACHING yes
2
3OK
4

订阅键空间事件

通过订阅键空间事件,客户端能够接收到指定键的变更通知。订阅通过 PSUBSCRIBE 命令实现:

1redis> PSUBSCRIBE "__keyspace@0__:mykey"
2

通知机制

Redis 服务器通过发布/订阅机制将变更通知推送给客户端。这通过 trackingInvalidateKey 和相关函数实现。

1. 启用键空间通知

首先,需要在 Redis 配置文件中启用键空间通知:

1notify-keyspace-events Ex
2

2. 处理键变更事件

当键发生变更时,Redis 会调用 trackingInvalidateKey 函数来处理变更事件。

1void trackingInvalidateKey(client *c, robj *keyobj) {
2    if (!keyobj) return;
3
4    sds sdskey = keyobj->ptr;
5    size_t keylen = sdslen(sdskey);
6
7    // 查找所有订阅该键的客户端并发送无效化消息
8    listNode *ln;
9    listIter li;
10    listRewind(server.tracking_clients, &li);
11    while ((ln = listNext(&li)) != NULL) {
12        client *target = listNodeValue(ln);
13        if (target == c) continue;
14
15        // 发送无效化消息
16        addReplyArrayLen(target, 2);
17        addReplyBulkCString(target, "invalidate");
18        addReplyBulk(target, keyobj);
19    }
20}
21

缓存一致性管理

为了确保客户端缓存的一致性,Redis 通过以下机制管理缓存:

1. 追踪表

Redis 维护一个追踪表,用于记录每个客户端订阅的键。

1typedef struct trackingTableEntry {
2    sds key;
3    client *c;
4} trackingTableEntry;
5
6dict *tracking_table;
7

2. 键变更通知

当键发生变更时,Redis 会遍历追踪表,查找订阅该键的客户端,并发送变更通知。

1void notifyKeyspaceEvent(int type, char *event, robj *key, int dbid) {
2    // 构建订阅频道名称
3    sds channel = sdsnewlen("__keyspace@", 11);
4    channel = sdscatprintf(channel, "%d__", dbid);
5    channel = sdscatsds(channel, key);
6
7    // 发送通知
8    list *clients = dictFetchValue(tracking_table, channel);
9    if (clients != NULL) {
10        listIter li;
11        listNode *ln;
12        listRewind(clients, &li);
13        while ((ln = listNext(&li)) != NULL) {
14            client *c = listNodeValue(ln);
15            if (c->flags & CLIENT_CLOSE_AFTER_REPLY) continue;
16            addReplyArrayLen(c, 3);
17            addReplyBulkCString(c, "message");
18            addReplyBulk(c, channel);
19            addReplyBulkCString(c, event);
20        }
21    }
22    sdsfree(channel);
23}
24

代码示例

以下是一个简单的代码示例,展示了如何在客户端启用缓存并处理键变更通知:

1#include <stdio.h>
2#include <stdlib.h>
3#include <hiredis/hiredis.h>
4
5void onMessage(redisAsyncContext *c, void *reply, void *privdata) {
6    redisReply *r = (redisReply *)reply;
7    if (r == NULL) return;
8    printf("Received message: %s\n", r->element[2]->str);
9}
10
11int main(int argc, char **argv) {
12    redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
13    if (c->err) {
14        printf("Error: %s\n", c->errstr);
15        return 1;
16    }
17
18    // 启用客户端缓存
19    redisAsyncCommand(c, NULL, NULL, "CLIENT CACHING yes");
20
21    // 订阅键空间事件
22    redisAsyncCommand(c, onMessage, NULL, "PSUBSCRIBE __keyspace@0__:mykey");
23
24    // 事件循环
25    redisAsyncSetConnectCallback(c, NULL);
26    redisAsyncSetDisconnectCallback(c, NULL);
27    redisAsyncCommand(c, NULL, NULL, "PING");
28
29    redisAsyncContext *sub = redisAsyncConnect("127.0.0.1", 6379);
30    redisAsyncCommand(sub, NULL, NULL, "SUBSCRIBE __keyspace@0__:mykey");
31
32    redisEventLoop(sub);
33
34    redisAsyncFree(c);
35    return 0;
36}
37

总结

Redis 的客户端缓存通过订阅机制和通知机制实现,确保客户端能够及时获取键的变更信息,从而保持缓存的一致性。通过启用客户端缓存和订阅键空间事件,客户端可以有效地减少与 Redis 服务器的通信频率,并显著提升应用的响应速度。上述代码示例展示了如何启用客户端缓存并处理键变更通知,以及 Redis 在后台如何管理和发送变更通知的实现细节。


Redis(136)Redis的客户端缓存是如何实现的?》 是转载文章,点击查看原文


相关推荐


【AI省流快讯】Cloudflare 炸了 / Gemini 3 来了 / Antigravity 独家实测 (附:无法登录解法)
coder_pig2025/11/19

1. Cloudflare 挂了 🤡 昨晚陆续刷到 "CF挂了" 的消息,没太在意,直到无法打开" 盗版漫画" 站点,我才意识到问题的严重性: 🤣 原因众说纷纭,刷到这哥们的 "梗图",差点把我笑岔气: 😃 还有人猜测可能是 Google 发布的 "哈基米 3" (Gemini) 发起的攻击: 时间线: 【19:30】用户开始报告网站无法访问,出现10xx、52x、50x系列错误;Cloudflare Dashboard无法访问;部分Cloudflare域名解析中断。 【19:4


Excel处理控件Aspose.Cells教程:使用Python从Excel工作表中删除数据透视表
IT开发者笔记2025/11/18

在使用 Excel 处理数据时,数据透视表通过汇总大型数据集,简化了分析过程。但随着分析的深入,您可能需要删除旧的数据透视表,以保持工作表的整洁或为新的分析结果做好准备。您可以快速删除任何数据透视表,无需手动查找,也不会留下任何失效的引用。本教程将逐步介绍如何借助Aspose.Cells使用Python从Excel 工作表中删除数据透视表。 Aspose.Cells官方试用版免费下载 本篇教程适合: 使用Excel高级用户自动生成每月演示文稿每周一都要重建仪表盘的数据分析师宁愿写五行代码也


用 TRAE SOLO 高效开发的 12 个小技巧
TRAE_ai2025/11/17

本文作者:云舒,TRAE 产品运营 用 SOLO 高效开发的 12 个技巧,从入门到精通,带你玩转 SOLO。 第一部分:入门篇 技巧 1:根据项目需求选择合适的内置智能体 TRAE SOLO 内置了两个核心智能体:SOLO Coder和 SOLO Builder,它们分别适用于不同的开发场景,明确场景后选择合适的智能体,能显著提升推进效率与结果质量。 如果你想处理基于现有代码库的迭代、重构和 Bug 修复等复杂任务,SOLO Coder 是最佳的选择,它具备优秀的项目理解和上下文管理能力


linux之ubuntu qt界面开发开发点菜系统
RouDragon2025/11/16

首先这篇博客主要讲解的是如何设计一个基于qt开发的点菜系统,这方面有很多内容会引用他人的文章需要继续学习他人的文章才会明白此文章是在讲解啥。 自制点菜系统视频链接 整体设计思路     这张图其实很详细的介绍了点菜系统需要的技术,在开发板方面,也就是服务器端,首先屏幕显示也是基于qt开发,所有你的ubuntu qt开发的时候就得设置好其编译器和环境基于开发板的,同时你还需要另一套环境进行直接在开发板上测试不需要反反复复的在开发板上重装。屏幕显示部分还需要首先设置一个登陆界面当客户


进入职场第五课——突破和跃升
Mapbarfront2025/11/14

观察、融入、立足、产出,度过这4个阶段之后,你已经稳稳地,成为团队里的主力输出了,接下来,如果你想从团队中的好员工,跃升为老板眼中的关键人物,从业务骨干到真正的团队核心,必须要做的下一步就是突破,易经乾卦中的或跃在渊,说的就是这个意思。 或是或许,代表着不确定性,跃是跳跃,代表着勇敢一搏,在渊是指在深渊里,代表着突破前在深渊里的等待,这个阶段,是你在积蓄了足够的力量之后,遇到合适的机会纵身一跃的时刻,这是审慎的冒险,也是耐心等待之后的水到渠成,想要完成这次关键的进阶,以下这5个动作,你要步步为营


uos基础 dmesg 查看内核的实时日志
行初心2025/11/13

统信桌面操作系统专业版V20(1070) Linux uos 5.10.97-arm64-desktop uos基础 dmesg 查看内核的实时日志 root@uos:~# dmesg -wH [11月10 14:59] [pid:3256,cpu1,Xwayland,1][HISI_DRM_HEAPS D]:do_alloc_memory: need alloc size=0x3000, now pool size=0x1a60000 [ +0.000000] [pid:3256,cpu1


苹果上线App Store Web版本,以后浏览外区更方便了
CocoaKier2025/11/12

近期,苹果低调上线了网页版 App Store(apps.apple.com/cn) 只要打开浏览器,用户就可以浏览AppStore了,即便非苹果设备也能访问,但目前只能浏览、搜索,不支持在网页端下载 app。 网页版的一个亮点是支持快速切换区域,我们只需修改网页地址中的区域代码即可快速浏览其他地区的 App Store 内容。这对于竞品分析,特别是出海产品的竞品分析,带来了非常大的便利,可以更方便快捷地查看某个国家地区的榜单,同类型应用有哪些,某个应用在不同地区的可用性、价格、评分、评论情况。


Day 7:05. 基于Nuxt开发博客项目-首页开发
申阳2025/11/10

一、前言 首页是站点的“脸面”,也是信息传达最直接的窗口。首页的设计质量,不仅关系到用户对站点的第一印象,更直接影响其使用体验与整体评价。因此,精心打造首页,至关重要。 我其实比较反感一些花里胡哨的页面,但是恰到好处的动画确实可以提高用户的体验,也利于网站推广。 我的目标是寻求平衡,信息作为主导,动画作为辅助。 下面开始我们的首页打造吧。 二、渐变文字标题 在tailwindcss的加持下,实现这种效果太方便了,只需要以下几个指令即可 <span class="ml-1 font-bold t


猿族代码战记:Mutex 升级版——守护 Swift 并发的“香蕉仓库”
大熊猫侯佩2025/11/8

🦍 引子 旧金山废墟的猿族技术区,金属支架撑起的荧光屏泛着冷光,首席 Swift 架构师科巴的指节因攥紧终端而发白 —— 食物计数系统又出问题了。 刚录入的 27 根香蕉,刷新页面竟变成 29,再点一下又跳回 28,旁边年轻猿工程师紧张地挠着头:“科巴大人,不会是小猩猩偷偷改数据吧?” 科巴瞪了他一眼:“是‘并发幽灵’!自从用 Actor 保护状态,简单的计数全成了麻烦 —— 查个库存要写await,就像咱们去仓库拿根香蕉,得先找凯撒签字、找后勤登记,折腾半小时!” 在本堂猩猩课堂中,您将学


保安公司的办理流程
2501_915837932025/11/5

北京保安公司还能新注册吗 哪里还能新注册保安公司 保安公司的收购流程与转让 保安公司转让信息与流程 一、保安公司注册核心要求与地区动态 全国统一基础标准根据《保安服务管理条例》及 2025 年最新执行细则,保安公司注册需满足: 1保安公司的人员资质:法人及至少 2 名高管必须持有二级保安师证书,且需提供无犯罪记录证明(含近 5 年无酒驾等行政违法记录)。退伍军人或有 25 年公安从业经历者,可凭相关证明免试获取报考资格。 2场地资金:商用办公地址面积因地区而异(北京 400㎡、武汉

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2025 聚合阅读