当前位置:首页 > 问答 > 正文

Redis缓存大小怎么调才合适,设置size那些事儿你知道吗

关于Redis缓存大小怎么调才合适这个问题,其实没有一个放之四海而皆准的“标准答案”,这就像问“一个人一顿饭吃多少才健康”一样,答案完全取决于他的体重、运动量和新陈代谢,Redis的缓存大小设置也同样如此,它高度依赖于你的业务场景、数据特性和服务器资源,我们可以围绕几个核心的方面来探讨,帮你找到最适合自己的那个“黄金尺寸”。

最根本的一点是:你的缓存大小绝对不能超过服务器的物理内存总量,这是底线,一旦越过这个红线,Redis就会开始使用硬盘上的交换空间(Swap),性能会呈现断崖式下跌,延迟会高到无法忍受,基本就等于缓存服务不可用了,在讨论“合适”之前,必须先确保“安全”。(来源:Redis官方文档中关于内存使用的警告)

在这个安全范围内,我们该如何确定具体的大小呢?关键要看你的缓存策略和数据的访问模式。

Redis缓存大小怎么调才合适,设置size那些事儿你知道吗

如果你的目标是缓存全部热点数据(即全量缓存或热数据缓存): 这种情况下,缓存大小的设定目标就是尽可能装下所有会被频繁访问的数据,你需要先估算出这些热点数据的总容量,你有一个用户系统,活跃用户大概100万,每个用户的信息大概占1KB,那么你至少需要预留1GB的内存给这部分数据,但这还不够,因为Redis本身运行也需要一些内存开销(比如维护数据结构、客户端连接等信息),比较稳妥的做法是,将缓存的最大值(maxmemory)设置为比你的热点数据总量多出20%-30%,这多出来的部分就是给Redis的操作留出的缓冲地带,避免因为瞬间的数据增长或者内部碎片而导致缓存被撑满。

如果你的缓存策略是只保留最新或最频繁访问的数据(即LRU或LFU算法淘汰策略): 这是更常见的场景,当缓存空间满了之后,Redis会根据你设定的规则(maxmemory-policy)自动淘汰掉一些数据,以便为新数据腾出空间,这时,缓存大小的设置就变成了一个权衡:设置得越大,缓存命中率就越高,访问数据库的压力就越小;设置得越小,内存消耗就越少,单次数据淘汰的成本也越低。

Redis缓存大小怎么调才合适,设置size那些事儿你知道吗

  • 如何权衡? 你需要关注一个核心指标:缓存命中率,你可以通过Redis的INFO命令查看keyspace_hitskeyspace_misses来计算命中率,一开始,你可以设置一个预估的大小,然后观察运行一段时间内的命中率,如果命中率一直很低(比如低于90%),并且你的服务器还有空闲内存,那就说明缓存空间可能不够用,很多请求因为没找到数据而直接访问了数据库,这时可以考虑适当调大缓存容量,反之,如果命中率已经很高了,而内存又比较紧张,或许可以尝试调小一点,看看命中率是否会显著下降,找到一个平衡点。(来源:普遍的系统性能优化实践)

除了数据本身,别忘了Redis的“后台员工” 设置缓存大小时,还有一个很容易被忽略的“隐形杀手”:持久化操作,当Redis执行RDB快照或AOF重写时,它可能会需要fork出一个子进程,在Linux系统中,fork操作会采用写时复制(Copy-on-Write)机制,如果你的缓存非常大,那么即使只修改了一小部分数据,也可能导致子进程复制大量的内存页面,从而瞬间占用接近两倍的内存。如果你的服务器需要开启持久化功能,那么你必须保证最大内存设置后,服务器仍有足够的空闲内存来应对fork操作带来的额外消耗,一般建议是,最大内存设置为总内存的70%-80%,剩下的留给操作系统和Redis的持久化操作。

设置方法本身也有讲究 在Redis配置文件redis.conf中,找到maxmemory这个参数,你可以用字节、KB、MB、GB等单位来设置,比如maxmemory 2gb,一定要配合设置maxmemory-policy这个淘汰策略,常见的策略有:

  • volatile-lru:只从设置了过期时间的键中淘汰最近最少使用的。
  • allkeys-lru:从所有键中淘汰最近最少使用的(最常用)。
  • volatile-ttl:淘汰即将过期的键。
  • noeviction:不淘汰,当内存不足时,新写入操作会报错(不推荐用于缓存场景)。 选择合适的淘汰策略和设置大小同等重要。

调优Redis缓存大小是一个动态的过程:

  • 起步:根据业务数据量预估一个值,并确保不超过总内存。
  • 观察:上线后,密切监控内存使用率、缓存命中率和系统负载。
  • 调整:根据监控数据,像调节水龙头一样,一点点地调整maxmemory的值,找到那个能让命中率和资源消耗达到最佳平衡点的位置。
  • 预留:永远为操作系统和Redis的内部操作(特别是持久化)留出充足的内存余量。

合适的缓存大小不是算出来的,而是通过持续的观察和调试“试”出来的。