内存耗尽后Redis会发生什么,腾讯Java面试必问

  • Redis 如何管理热度数据

  • LFU 算法

    • 访问频次递增
  • 访问频次递减

  • 总结

前言

===============================================================

作为一台服务器来说,内存并不是无限的,所以总会存在内存耗尽的情况,那么当 Redis 服务器的内存耗尽后,如果继续执行请求命令,Redis 会如何处理呢?

内存回收

=================================================================

使用Redis 服务时,很多情况下某些键值对只会在特定的时间内有效,为了防止这种类型的数据一直占有内存,我们可以给键值对设置有效期。Redis 中可以通过 4 个独立的命令来给一个键设置过期时间:

  • expire key ttl:将 key 值的过期时间设置为 ttl

  • pexpire key ttl:将 key 值的过期时间设置为 ttl 毫秒

  • expireat key timestamp:将 key 值的过期时间设置为指定的 timestamp 秒数

  • pexpireat key timestamp:将 key 值的过期时间设置为指定的 timestamp 毫秒数

PS:不管使用哪一个命令,最终 Redis 底层都是使用 pexpireat 命令来实现的。另外,set 等命令也可以设置 key 的同时加上过期时间,这样可以保证设值和设过期时间的原子性。

设置了有效期后,可以通过 ttlpttl 两个命令来查询剩余过期时间(如果未设置过期时间则下面两个命令返回 -1,如果设置了一个非法的过期时间,则都返回 -2):

  • ttl key 返回 key 剩余过期秒数。

  • pttl key 返回 key 剩余过期的毫秒数。

过期策略


如果将一个过期的键删除,我们一般都会有三种策略:

  • 定时删除:为每个键设置一个定时器,一旦过期时间到了,则将键删除。这种策略对内存很友好,但是对 CPU 不友好,因为每个定时器都会占用一定的 CPU 资源。

  • 惰性删除:不管键有没有过期都不主动删除,等到每次去获取键时再判断是否过期,如果过期就删除该键,否则返回键对应的值。这种策略对内存不够友好,可能会浪费很多内存。

  • 定期扫描:系统每隔一段时间就定期扫描一次,发现过期的键就进行删除。这种策略相对来说是上面两种策略的折中方案,需要注意的是这个定期的频率要结合实际情况掌控好,使用这种方案有一个缺陷就是可能会出现已经过期的键也被返回。

Redis 当中,其选择的是策略 2 和策略 3 的综合使用。不过 Redis 的定期扫描只会扫描设置了过期时间的键,因为设置了过期时间的键 Redis 会单独存储,所以不会出现扫描所有键的情况:

typedef struct redisDb {

dict *dict; //所有的键值对

dict *expires; //设置了过期时间的键值对

dict *blocking_keys; //被阻塞的key,如客户端执行BLPOP等阻塞指令时

dict *watched_keys; //WATCHED keys

int id; //Database ID

//… 省略了其他属性

} redisDb;

8 种淘汰策略


假如 Redis 当中所有的键都没有过期,而且此时内存满了,那么客户端继续执行 set 等命令时 Redis 会怎么处理呢?Redis 当中提供了不同的淘汰策略来处理这种场景。

首先 Redis 提供了一个参数 maxmemory 来配置 Redis 最大使用内存:

maxmemory

或者也可以通过命令 config set maxmemory 1GB 来动态修改。

如果没有设置该参数,那么在 32 位的操作系统中 Redis 最多使用 3GB 内存,而在 64 位的操作系统中则不作限制。

Redis 中提供了 8 种淘汰策略,可以通过参数 maxmemory-policy 进行配置:

| 淘汰策略 | 说明 |

| — | — |

| volatile-lru | 根据 LRU 算法删除设置了过期时间的键,直到腾出可用空间。如果没有可删除的键对象,且内存还是不够用时,则报错 |

| allkeys-lru | 根据 LRU 算法删除所有的键,直到腾出可用空间。如果没有可删除的键对象,且内存还是不够用时,则报错 |

| volatile-lfu | 根据 LFU 算法删除设置了过期时间的键,直到腾出可用空间。如果没有可删除的键对象,且内存还是不够用时,则报错 |

| allkeys-lfu | 根据 LFU 算法删除所有的键,直到腾出可用空间。如果没有可删除的键对象,且内存还是不够用时,则报错 |

| volatile-random | 随机删除设置了过期时间的键,直到腾出可用空间。如果没有可删除的键对象,且内存还是不够用时,则报错 |

| allkeys-random | 随机删除所有键,直到腾出可用空间。如果没有可删除的键对象,且内存还是不够用时,则报错 |

| volatile-ttl | 根据键值对象的 ttl 属性, 删除最近将要过期数据。 如果没有,则直接报错 |

| noeviction | 默认策略,不作任何处理,直接报错 |

PS:淘汰策略也可以直接使用命令 config set maxmemory-policy <策略> 来进行动态配置。

LRU 算法


LRU 全称为:Least Recently Used。即:最近最长时间未被使用。这个主要针对的是使用时间。

Redis 改进后的 LRU 算法

Redis 当中,并没有采用传统的 LRU 算法,因为传统的 LRU 算法存在 2 个问题:

  • 需要额外的空间进行存储。

  • 可能存在某些 key 值使用很频繁,但是最近没被使用,从而被 LRU 算法删除。

为了避免以上 2 个问题,Redis 当中对传统的 LRU 算法进行了改造,通过抽样的方式进行删除

配置文件中提供了一个属性 maxmemory_samples 5,默认值就是 5,表示随机抽取 5key 值,然后对这 5key 值按照 LRU 算法进行删除,所以很明显,key 值越大,删除的准确度越高。

对抽样 LRU 算法和传统的 LRU 算法,Redis 官网当中有一个对比图:

  • 浅灰色带是被删除的对象。

  • 灰色带是未被删除的对象。

  • 绿色是添加的对象。

在这里插入图片描述

左上角第一幅图代表的是传统 LRU 算法,可以看到,当抽样数达到 10 个(右上角),已经和传统的 LRU 算法非常接近了。

Redis 如何管理热度数据

前面我们讲述字符串对象时,提到了 redisObject 对象中存在一个 lru 属性:

typedef struct redisObject {

unsigned type:4;//对象类型(4位=0.5字节)

unsigned encoding:4;//编码(4位=0.5字节)

unsigned lru:LRU_BITS;//记录对象最后一次被应用程序访问的时间(24位=3字节)

int refcount;//引用计数。等于0时表示可以被垃圾回收(32位=4字节)

void *ptr;//指向底层实际的数据存储结构,如:SDS等(8字节)

} robj;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

总结

这份面试题几乎包含了他在一年内遇到的所有面试题以及答案,甚至包括面试中的细节对话以及语录,可谓是细节到极致,甚至简历优化和怎么投简历更容易得到面试机会也包括在内!也包括教你怎么去获得一些大厂,比如阿里,腾讯的内推名额!

某位名人说过成功是靠99%的汗水和1%的机遇得到的,而你想获得那1%的机遇你首先就得付出99%的汗水!你只有朝着你的目标一步一步坚持不懈的走下去你才能有机会获得成功!

成功只会留给那些有准备的人!

总结

这份面试题几乎包含了他在一年内遇到的所有面试题以及答案,甚至包括面试中的细节对话以及语录,可谓是细节到极致,甚至简历优化和怎么投简历更容易得到面试机会也包括在内!也包括教你怎么去获得一些大厂,比如阿里,腾讯的内推名额!

某位名人说过成功是靠99%的汗水和1%的机遇得到的,而你想获得那1%的机遇你首先就得付出99%的汗水!你只有朝着你的目标一步一步坚持不懈的走下去你才能有机会获得成功!

成功只会留给那些有准备的人!

[外链图片转存中…(img-U8SqRwC0-1712062902196)]

  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值