客户端缓存介绍
Redis 中的服务器辅助客户端缓存
客户端缓存减少了 Redis 客户端和服务器之间的网络流量,通常可以提高性能。
默认情况下,应用服务器(位于用户应用和数据库之间)通过客户端库向 Redis 数据库服务器发送每个读取请求。下图显示了从用户应用、通过应用服务器到数据库再返回的通信流程
使用客户端缓存时,客户端库在从数据库检索数据项时会维护这些数据项的本地缓存。当再次需要相同的项时,客户端可以直接从缓存满足读取请求,而不是访问数据库
访问缓存比通过网络与数据库通信快得多,并且减少了网络流量。客户端缓存减轻了数据库服务器的负载,因此您可以使用更少的硬件资源来运行它。
与其他形式的缓存一样,客户端缓存在非常常见的使用场景中表现良好,即只有一小部分数据被访问的频率远高于其余数据(根据帕累托法则)。
数据更改时更新缓存
所有缓存系统都必须实现一种方案,以便在主数据库中相应数据发生更改时更新缓存中的数据。Redis 使用一种称为跟踪的方法。
启用客户端缓存后,Redis 服务器会记住或跟踪每个客户端连接之前读取过的键集。这包括客户端直接读取数据的情况(例如使用 GET
命令),也包括服务器从存储的数据计算值的情况(例如使用 STRLEN
)。当任何客户端向被跟踪的键写入新数据时,服务器会向所有之前访问过该键的客户端发送一个失效消息。此消息会警告客户端其缓存的数据副本不再有效,并且客户端会响应性地驱逐过时数据。下次客户端读取同一键时,它将直接访问数据库并使用更新后的数据刷新其缓存。
下面的序列图显示了两个客户端在访问和更新同一个键时可能如何交互
哪些客户端库支持客户端缓存?
以下客户端库从所示版本起支持客户端缓存(CSC)
客户端 | 版本 |
---|---|
redis-py |
v5.1.0 |
Jedis |
v5.2.0 |
哪些命令可以缓存数据?
所有只读命令(带有 @read
ACL 分类)都将使用缓存数据,但以下命令除外
- 用于概率型和时间序列型数据类型的任何命令。这些类型设计为频繁更新,这意味着缓存几乎没有或没有任何好处。
- 非确定性命令,例如
HRANDFIELD
、HSCAN
和ZRANDMEMBER
。根据设计,这些命令每次调用都会给出不同的结果。 - Redis 查询引擎命令(带有
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 客户端使用,但对于自定义客户端和其他高级应用可能有用。请参阅客户端缓存参考,获取有关客户端缓存所有可用选项的完整技术指南。