对线面试官 -Redis(内存消耗的问题)
面试官:Hi,上次我们聊到了 Redis 作为缓存的数据一致性问题,这次我们继续聊一聊 Redis 作为缓存的问题之内存消耗问题?
其实这里问到内存消耗的问题其实无非是想要了解 Redis 的内存回收机制,或者说更侧重于是 Redis 的淘汰策略,只要不偏离这方面去回答,我认为问题是不大的。
派大星:好的,没问题。内存消耗问题,就涉及到关于 Redis 的内存回收机制。说到 Redis 的内存回收机制,其实主要分为两个方面。
Redis 过期策略:删除过期时间的 key 值
Redis 淘汰策略:内存使用达到了 Max Memory 上限时会触发内存淘汰数据
派大星:其实我们在开发过程种一定要注意:Redis 的过期策略和内存淘汰策略不是一件事,千万不要混淆
面试官:不错,你能详细聊一聊关于这两个回收机制吗?
派大星:可以的,首先先说一下 Redis 过期策略,过期策略通常有以下 3 种:
定时过期:对内存来说是友好的
每个设置过期时间的 key 都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的 CPU 资源去处理过期的数据,从而影响缓存的响应时间和吞吐量每个设置过期时间的 key 都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的 CPU 资源去处理过期的数据,从而影响缓存的响应时间和吞吐量
惰性过期:对 cpu 来说是友好的
只有当访问一个 key 时,才会判断该 key 是否已过期,过期则清除。该策略可以最大化地节省 CPU 资源,却对内存非常不友好。极端情况可能出现大量的过期 key 没有再次被访问,从而不会被清除,占用大量内存。
定期过期
每隔一定的时间,会扫描一定数量的数据库的 expires 字典中一定数量的 key,并清除其中已过期的 key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得 CPU 和内存资源达到最优的平衡效果。
派大星:Redis 中同时使用了惰性过期和定期过期两种过期策略。具体可参考官方文档:
官方文档:https://redis.io/commands/expire/
面试官:不错不错,那能再聊一聊 Redis 淘汰策略吗?
派大星:好的,关于 Redis 淘汰策略的基本概念就是:是指当内存使用达到 Max Memory 上限时,需要使用淘汰算法来决定清理掉哪些数据,以保证新数据的存入。Redis 默认情况下就是使用 LRU 策略算法。
面试官:很好,Redis 数据淘汰策略规则具体有哪些,能简单说一说吗?
派大星:可以,具体的数据淘汰策略如下:
noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key。
allkeys-lfu:根据键的访问频率来判断哪些键使用得最少,然后将访问频率较低的键进行淘汰
在使用 allkeys-lfu 策略时,Redis 会记录每个键的访问频率,并根据访问频率来判断哪些键应该被淘汰。访问频率低的键会更容易被淘汰,而访问频率高的键则更有可能被保留在内存中。
要注意的是,使用 allkeys-lfu 策略会带来一些额外的计算开销,因为 Redis 需要跟踪键的访问频率。因此,在选择淘汰策略时,需要根据实际需求权衡淘汰的准确性和计算开销之间的关系
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 key。
volatile-lfu:Redis 会根据键的访问频率和过期时间来判断哪些设置了过期时间的键应该被淘汰。访问频率低且过期时间较早的键会更容易被淘汰,而访问频率高或过期时间较晚的键则更有可能被保留在内存中
allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 key。
volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 key。
volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 key 优先移除。
也可参考官网:https://redis.io/docs/reference/eviction/
面试官:那你能说说 Redis 过期策略和 Redis 淘汰策略具体什么区别吗?
派大星:Redis 的内存淘汰策略用于处理内存不足时的需要申请额外空间的数据,内存淘汰策略的选取并不会影响过期的 key 的处理。过期策略用于处理过期的缓存数据
面试官:非常好,那你能说下 Redis 数据淘汰策略如何进行配置吗?
派大星:可以通过 maxmemory-policy 进行配置,设置内存达到最大闲置后,采取什么策略来处理。maxmemory 用来设置 redis 存放数据的最大的内存大小,一旦超出这个内存大小之后,就会立即使用 LRU 算法清理掉部分数据。对于 64 bit 的机器,如果 maxmemory 设置为 0,那么就默认不限制内存的使用,直到耗尽机器中所有的内存为止;,但是对于 32 bit 的机器,有一个隐式的闲置就是 3GB。
派大星: 随着业务的增多,缓存数据必然会越来越多,所占用的内存也随之增多,系统的压力也会变大,这时一种方式是给 key 设置过期时间,但是过期时间长短不太好把握,这时我们可以通过设置 redis 最大内存来实现,并让 redis 按照一定的规则淘汰不需要的缓存键,通过这种方式可以去缓解内存消耗的问题。
面试官:很好,那你知道 RDB 和 AOF 的淘汰处理吗?
派大星:了解一些
在 RDB 中是以快照的形式获取内存中某一时间点的数据副本,在创建 RDB 文件的时候可以通过 save 和 bgsave 命令执行创建 RDB 文件。这两个命令都不会把过期的 key 保存到 RDB 文件中,这样也能达到删除过期 key 的效果。当在启动 Redis 载入 RDB 文件的时候,Master 不会把过期的 key 载入,而 Slave 会把过期的 key 载入。
在 AOF 模式下,Redis 提供了 Rewite 的优化措施,执行的命令分别是 REWRITEAOF 和 BGREWRITEAOF,这两个命令都不会把过期的 key 写入到 AOF 文件中,也能删除过期 key。
面试官:非常好。你对 Redis 的了解还是比较透彻的,那么我们下一次再聊一聊,关于 Redis 作为缓存更新延迟的问题吧。
派大星:好的,没问题。
如有问题,欢迎加微信交流:w714771310,或关注微信公众号【码上遇见你】。
版权声明: 本文为 InfoQ 作者【派大星】的原创文章。
原文链接:【http://xie.infoq.cn/article/7876e81ec0dacb1a4527ff338】。
本文遵守【CC BY-NC-ND】协议,转载请保留原文出处及本版权声明。
评论