首页 > 数据库 >[微服务]redis内存回收原理

[微服务]redis内存回收原理

时间:2025-01-13 09:29:33浏览次数:3  
标签:KEY 过期 redis Redis 回收 访问 内存 key

过期KEY处理

Redis提供了expire命令,给key设置TTL(存活时间)

可以发现,当key的TTL到期以后,再次访问name返回的是nil,说明这个key已经不存在了,对应的内存也得到释放从而起到内存回收的目的。

这里有两个问题需要我们思考:

  1. Redis是如何知道一个key是否过期呢?

Redis的本身是键值型数据库,其所有数据都存在一个redisDB的结构体中,其中包含两个哈希表:

  • dict: 保存Redis中所有的键值对
  • expires: 保存Redis中所有的设置了过期时间的KEY及其到期时间(写入时间+TTL)

  1. 是不是TTL到期就立即删除了呢?

Redis并不会实时监测key的过期时间,在key过期后立刻删除。而是采用两种延迟删除的策略:

惰性删除: 当有命令需要操作一个key的时候,检查该key的存活时间,如果已经过期才执行删除。

周期删除: 通过一个定时任务,周期性的抽样部分有TTL的key,如果过期则执行删除。

周期删除的定时任务执行周期有两种:

SLOW模式: 默认执行频率为每秒10次,但每次执行时长不能超过25ms,受server.hz参数影响

FAST模式: 频率不固定,跟随Redis内部I0事件循环执行。两次任务之间间隔不低于2ms,执行时长不超过1ms

小结

  1. RedisKey的TTL记录方式:

在RedisDB中通过一个哈希表记录每个Key的到期时间

  1. 期key的删除策略:

惰性清理: 每次查找key时判断是否过期,如果过期则删除

定期清理: 定期抽样部分key,判断是否过期,如果过期则删除。

  1. 定期清理的两种模式:

SLOW模式执行频率默认为10,每次不超过25ms

FAST模式执行频率不固定,但两次间隔不低于2ms,每次耗时不超过1ms

内存淘汰策略

对于某些特别依赖于Redis的项目而言,仅仅依靠过期KEY清理是不够的,内存可能很快就达到上限。因此Redis允许设置内存告警阈值,当内存使用达到阈值时就会主动挑选部分KEY删除以释放更多内存。这叫做内存淘汰机制。

内存淘汰时机

那么问题来了,当内存达到阈值时执行内存淘汰,但问题是Redis什么时候会执去判断内存是否达到预警呢?

Redis每次执行任何命令时,都会判断内存是否达到阈值:

// server.c中处理命令的部分源码
int processCommand(client *c) {
    // ... 略
    if (server.maxmemory && !server.lua_timedout) {
        // 调用performEvictions()方法尝试进行内存淘汰
        int out_of_memory = (performEvictions() == EVICT_FAIL);
        // ... 略
        if (out_of_memory && reject_cmd_on_oom) {
            // 如果内存依然不足,直接拒绝命令
            rejectCommand(c, shared.oomerr);
            return C_OK;
        }
    }
}

淘汰策略

好了,知道什么时候尝试淘汰了,那具体Redis是如何判断该淘汰哪些Key的呢?

Redis支持8种不同的内存淘汰策略:

  • noeviction: 不淘汰任何key,但是内存满时不允许写入新数据,默认就是这种策略。
  • volatile-ttl: 对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰
  • allkeys-random:对全体key ,随机进行淘汰。也就是直接从db->dict中随机挑选
  • volatile-random:对设置了TTL的key ,随机进行淘汰。也就是从db->expires中随机挑选。
  • allkeys-lru: 对全体key,基于LRU算法进行淘汰
  • volatile-lru: 对设置了TTL的key,基于LRU算法进行淘汰
  • allkeys-lfu: 对全体key,基于LFU算法进行淘汰
  • volatile-lfu: 对设置了TTL的key,基于LFI算法进行淘汰

比较容易混淆的有两个算法:

  • LRULeast Recently Used),最近最久未使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。
  • LFULeast Frequently Used),最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高。

Redis怎么知道某个KEY的最近一次访问时间或者是访问频率呢?

  1. Redis的数据都会被封装为RedisObject结构

  1. 其中的lru就是记录最近一次访问时间和访问频率的。当然,你选择LRULFU时的记录方式不同:
  • LRU:以秒为单位记录最近一次访问时间,长度24bit
  • LFU:高16位以分钟为单位记录最近一次访问时间,低8位记录逻辑访问次数
  1. 时间就不说了,那么逻辑访问次数又是怎么回事呢?8位无符号数字最大才255,访问次数超过255怎么办?
  2. 这就要聊起Redis的逻辑访问次数算法了,LFU的访问次数之所以叫做逻辑访问次数,是因为并不是每次key被访问都计数,而是通过运算:
  • ① 生成[0,1)之间的随机数R
  • ② 计算 1/(旧次数 * lfu_log_factor + 1),记录为Plfu_log_factor默认为10
  • ③ 如果 R < P ,则计数器 +1,且最大不超过255
  • ④ 访问次数会随时间衰减,距离上一次访问时间每隔 lfu_decay_time 分钟(默认1) ,计数器-1
  1. 显然LFU的基于访问频率的统计更符合我们的淘汰目标,因此官方推荐使用LFU算法。

算法我们弄明白了,不过这里大家要注意一下:

Redis中的KEY可能有数百万甚至更多,每个KEY都有自己访问时间或者逻辑访问次数。我们要找出时间最早的或者访问次数最小的,难道要把Redis中所有数据排序

  1. 要知道Redis的内存淘汰是在每次执行命令时处理的。如果每次执行命令都先对全量数据做内存排序,那命令的执行时长肯定会非常长,这是不现实的。
  2. 所以Redis采取的是抽样法,即每次抽样一定数量(maxmemory_smples)的key,然后基于内存策略做排序,找出淘汰优先级最高的,删除这个key。这就导致Redis的算法并不是真正的LRU,而是一种基于抽样的近似LRU算法
  3. 不过,在Redis3.0以后改进了这个算法,引入了一个淘汰候选池,抽样的key要与候选池中的key比较淘汰优先级,优先级更高的才会被放入候选池。然后在候选池中找出优先级最高的淘汰掉,这就使算法的结果更接近与真正的LRU算法了。特别是在抽样值较高的情况下(例如10),可以达到与真正的LRU接近的效果。
  4. 这也是官方给出的真正LRU与近似LRU的结果对比:

你可以在图表中看到三种颜色的点形成三个不同的带,每个点就是一个加入的KEY

  • 浅灰色带是被驱逐的对象
  • 灰色带是没有被驱逐的对象
  • 绿色带是被添加的对象

小结

面试题Redis如何判断KEY是否过期呢?

:在Redis中会有两个Dict,也就是HashTable,其中一个记录KEY-VALUE键值对,另一个记录KEY和过期时间。要判断一个KEY是否过期,只需要到记录过期时间的Dict中根据KEY查询即可。

面试题Redis何时删除过期KEY?如何删除?

:Redis的过期KEY处理有两种策略,分别是惰性删除和周期删除。

惰性删除是指在每次用户访问某个KEY时,判断KEY的过期时间:如果过期则删除;如果未过期则忽略。

周期删除有两种模式:

  • SLOW模式:通过一个定时任务,定期的抽样部分带有TTL的KEY,判断其是否过期。默认情况下定时任务的执行频率是每秒10次,但每次执行不能超过25毫秒。如果执行抽样后发现时间还有剩余,并且过期KEY的比例较高,则会多次抽样。
  • FAST模式:在Redis每次处理NIO事件之前,都会抽样部分带有TTL的KEY,判断是否过期,因此执行频率较高。但是每次执行时长不能超过1ms,如果时间充足并且过期KEY比例过高,也会多次抽样

面试题当Redis内存不足时会怎么做

:这取决于配置的内存淘汰策略,Redis支持很多种内存淘汰策略,例如LRU、LFU、Random. 但默认的策略是直接拒绝新的写入请求。而如果设置了其它策略,则会在每次执行命令后判断占用内存是否达到阈值。如果达到阈值则会基于配置的淘汰策略尝试进行内存淘汰,直到占用内存小于阈值为止。

面试题那你能聊聊LRULFU

LRU是最近最久未使用。Redis的Key都是RedisObject,当启用LRU算法后,Redis会在Key的头信息中使用24个bit记录每个key的最近一次使用的时间lru。每次需要内存淘汰时,就会抽样一部分KEY,找出其中空闲时间最长的,也就是now - lru结果最大的,然后将其删除。如果内存依然不足,就重复这个过程。

由于采用了抽样来计算,这种算法只能说是一种近似LRU算法。因此在Redis4.0以后又引入了LFU算法,这种算法是统计最近最少使用,也就是按key的访问频率来统计。当启用LFU算法后,Redis会在key的头信息中使用24bit记录最近一次使用时间和逻辑访问频率。其中高16位是以分钟为单位的最近访问时间,后8位是逻辑访问次数。与LFU类似,每次需要内存淘汰时,就会抽样一部分KEY,找出其中逻辑访问次数最小的,将其淘汰。

面试题逻辑访问次数是如何计算的

:由于记录访问次数的只有8bit,即便是无符号数,最大值只有255,不可能记录真实的访问次数。因此Redis统计的其实是逻辑访问次数。这其中有一个计算公式,会根据当前的访问次数做计算,结果要么是次数+1,要么是次数不变。但随着当前访问次数越大,+1的概率也会越低,并且最大值不超过255.

除此以外,逻辑访问次数还有一个衰减周期,默认为1分钟,即每隔1分钟逻辑访问次数会-1。这样逻辑访问次数就能基本反映出一个key的访问热度了。

标签:KEY,过期,redis,Redis,回收,访问,内存,key
From: https://blog.csdn.net/CSDN20221005/article/details/145106275

相关文章

  • 数据在内存的存储
    数据类型介绍前面我们已经学习了基本的内置类型:(后边跟的是字节)char    //字符数据类型  1字节 打印%c      short   //短整型    2字节  打印%hdint    //整形    4字节  打印%dlong ......
  • G1原理—5.G1垃圾回收过程之Mixed GC
    大纲1.MixedGC混合回收是什么2.YGC可作为MixedGC的初始标记阶段3.MixedGC并发标记算法详解(一)4.MixedGC并发标记算法详解(二)5.MixedGC并发标记算法详解(三)6.并发标记的三色标记法7.三色标记法如何解决错标漏标问题8.SATB如何解决错标漏标问题9.重新梳理MixedGC......
  • JVM内存模型:Java的秘密引擎
    Java虚拟机(JVM)内存模型是Java程序性能优化和代码调优的核心。理解JVM内存模型对于编写高效、稳定的Java程序至关重要。1.1JVM内存模型概述JVM内存模型定义了Java程序中变量的存储位置以及变量在不同线程间可见性、访问权限等规则。它包括以下几个主要部分:方法区(MethodAr......
  • Redis 是一个开源的高性能键值对存储数据库,通常被用作缓存、消息队列和持久化数据库。
    Redis服务器是什么?Redis是一个开源的高性能键值对存储数据库,通常被用作缓存、消息队列和持久化数据库。Redis支持多种数据结构,如字符串、哈希、列表、集合、有序集合、位图等。它被广泛用于需要快速读写操作、低延迟的场景。Redis可以作为一个独立的数据库使用,也可以作为缓......
  • redis-shake工具同步redis数据
    一、我的使用场景说明1.业务场景由于业务要求,redis服务器迁移,将A服务器redis(单机)数据迁移到B服务器的redis(单机)上,只迁移5库数据,选择工具的原因是:B服务器上redis其他库都有数据,不能直接迁移A服务器redis的rdb或aof持久化文件redis都是单机、6.0.2版本redis使用docker容器部署......
  • Prometheus 是一个开源的监控和报警工具,主要用于收集、存储和查询来自不同服务和应用
    Prometheus是什么?Prometheus是一个开源的监控和报警工具,主要用于收集、存储和查询来自不同服务和应用程序的时间序列数据(如CPU使用率、内存消耗、网络流量等)。它特别适合用于微服务架构下的监控,因为它支持多种集成方式,并能够处理大规模的、高频的数据。Prometheus具有以下主......
  • 【Web攻防】为什么说内存马正在改变Web安全格局?8年技术进化史
    前言在当今Web安全领域,内存马已成为绕过传统防御体系的重要技术。传统Webshell在面对以下防御时往往难以有效存活:文件监控、防篡改、EDR等终端安全Webshell特征检测和流量监控防火墙阻断反连及反向代理隐藏真实IP在这样的背景下,无文件攻击、内存Webshell等基于内存的攻击......
  • STM32中的内存映射
     STM32中的内存映射在STM32中,内存映射通常如下:Flash:存储.text段(代码)、.rodata段(只读数据)和.data段的初始值。RAM:存储.data段(运行时)、.bss段、栈和堆。4. 程序启动过程在STM32中,程序启动时会发生以下操作:从Flash中加载.data段的初始值到RAM。将.bss......
  • G1原理—4.G1垃圾回收的过程之Young GC
    大纲1.G1的YGC过程2.YGC并行处理阶段的过程3.YGC串行处理阶段的过程(一)4.YGC串行处理阶段的过程(二)5.整个YGC的执行流程总结 1.G1的YGC过程(1)YGC相关的一些参数(2)YGC和MixedGC、FGC之间的关系(3)YGC使用的算法+新生代的垃圾回收流程 (1)YGC相关的一些参数一.......
  • G1原理—4.G1垃圾回收的过程之Young GC
    大纲1.G1的YGC过程2.YGC并行处理阶段的过程3.YGC串行处理阶段的过程(一)4.YGC串行处理阶段的过程(二)5.整个YGC的执行流程总结1.G1的YGC过程(1)YGC相关的一些参数(2)YGC和MixedGC、FGC之间的关系(3)YGC使用的算法+新生代的垃圾回收流程(1)YGC相关的一些参数一.-......