客户端缓存简介
提示
来自deepseek解释
原文链接:https://redis.io/docs/latest/develop/clients/client-side-caching/
客户端缓存可以减少 Redis 客户端与服务器之间的网络流量,从而通常能提升性能。
默认情况下,应用服务器(位于用户应用和数据库之间)会通过客户端库为每个读请求联系 Redis 数据库服务器。下图展示了从用户应用出发,经过应用服务器到达数据库再返回的通信流程:
当您使用客户端缓存时,客户端库会在从数据库中检索数据项时,在本地维护一个数据缓存。当再次需要相同的数据项时,客户端可以从缓存中满足读请求,而无需访问数据库:
访问缓存比通过网络与数据库通信要快得多,并且减少了网络流量。客户端缓存减轻了数据库服务器的负载,因此您可能可以使用更少的硬件资源来运行它。
与其他形式的缓存一样,客户端缓存在一种非常常见的场景中表现良好,即一小部分数据被访问的频率远高于其余数据(根据帕累托原则)。
数据变化时更新缓存
所有缓存系统都必须实现一种方案,以便当主数据库中的相应数据发生变化时更新缓存中的数据。Redis 使用一种称为*追踪(tracking)*的方法。
当启用客户端缓存时,Redis 服务器会记住或追踪每个客户端连接先前已读取的键集合。这包括客户端直接读取数据的情况(如 GET 命令),也包括服务器根据存储数据计算值的情况(如 STRLEN)。当任何客户端向被追踪的键写入新数据时,服务器会向所有先前访问过该键的客户端发送失效消息。此消息警告客户端其缓存的数据副本已不再有效,客户端将相应驱逐过时的数据。下次客户端从同一个键读取时,它将直接访问数据库,并使用更新后的数据刷新其缓存。
如果来自客户端的任何连接断开(包括来自连接池的连接),客户端将清空客户端缓存中的所有键。随后,缓存将在仍活跃的连接上的后续读取中恢复。
下面的时序图展示了两个客户端在访问和更新同一个键时可能如何交互:
哪些客户端库支持客户端缓存?
从以下版本开始,以下客户端库支持 CSC(客户端缓存):
| 客户端 | 版本 |
|---|---|
redis-py | v5.1.0 |
Jedis | v5.2.0 |
node-redis | v5.1.0 |
请注意,其他一些客户端支持 CLIENT TRACKING 命令来在服务器上配置 CSC,但这并不意味着它们本身支持 CSC 所需的功能。
哪些命令可以缓存数据?
所有只读命令(具有 @read ACL 类别)都将使用缓存数据,但以下命令除外:
- 任何针对概率和时间序列数据类型的命令。这些类型设计为频繁更新,这意味着缓存几乎没有或没有好处。
- 非确定性命令,例如
HRANDFIELD、HSCAN和ZRANDMEMBER。根据设计,这些命令每次调用都会给出不同的结果。 - Redis Search 命令(带有
FT.*前缀),例如FT.SEARCH。
您可以使用 MONITOR 命令来检查使用客户端缓存时服务器的行为。由于 MONITOR 仅报告来自服务器的活动,您应该会发现第一次可缓存的键访问会导致服务器响应。然而,后续访问由缓存满足,因此如果客户端缓存正常工作,MONITOR 应报告没有服务器活动。
命令会缓存哪些数据?
概括地说,命令调用的特定响应中的数据在首次使用后会被缓存。该数据的子集或从中计算出的值会照常从服务器检索,然后分别缓存。例如:
- 通过
GET检索的整个字符串会被添加到缓存中。通过SUBSTR检索的同一字符串的部分内容会在服务器上首次计算,然后与原始字符串分开缓存。 - 对字符串使用
GETBIT或BITFIELD会将返回的值与原始字符串分开缓存。 - 对于通过键访问的复合数据类型(哈希、JSON、集合和有序集合),整个对象会与各个字段分开缓存。因此,
JSON.GET mykey $和JSON.GET mykey $.myfield的结果会在缓存中创建单独的条目。 - 来自列表、流和有序集合的范围会与它们所属的对象分开缓存。同样,由
SINTER和SDIFF返回的子集也会创建单独的缓存条目。 - 对于多键读命令(如
MGET),键的顺序很重要。例如,MGET name:1 name:2与MGET name:2 name:1分开缓存,因为服务器会按您指定的顺序返回值。 - 从数据类型计算出的布尔值或数值(例如
SISMEMBER和LLEN)会与它们所引用的对象分开缓存。
使用建议
像任何缓存系统一样,客户端缓存也有一些局限性:
- 缓存只有有限的内存可用。当达到限制时,客户端必须驱逐可能有用的项以便为新项腾出空间。
- 缓存未命中、追踪和失效消息总是会增加轻微的性能开销。
以下是一些指导原则,可帮助您在这些限制内高效使用客户端缓存:
- 对非缓存友好的数据使用单独的连接:缓存对于频繁读取且不频繁更新的键能带来最大收益。但是,您也可能有频繁更新的数据,例如计数器和计分板。在这种情况下,失效消息的性能开销可能大于缓存带来的节省。通过对任何非缓存友好的数据使用不带客户端缓存的单独连接来避免此问题。
- 估算您可以缓存多少项:客户端库允许您指定要在缓存中保留的最大项数。您可以通过将缓存的最大期望内存大小除以要存储的项的平均大小来估算此数字(使用
MEMORY USAGE命令获取键的内存占用)。例如,如果您有 10MB(或 10485760 字节)可用于缓存,并且项的平均大小为 80 字节,则缓存中大约可以容纳 10485760 / 80 = 131072 个项。使用真实的测试负载监视服务器上的内存使用情况,以向上或向下调整您的估算。
参考
Redis 服务器为客户端缓存实现了额外功能,这些功能未被主要的 Redis 客户端使用,但可能对自定义客户端和其他高级应用有用。请参阅客户端缓存参考以获取有关客户端缓存所有可用选项的完整技术指南。