[redis 源码走读] - maxmemory 数据淘汰策略

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

redis 是内存数据库,可以通过 redis.conf 配置 maxmemory,限制 redis 内存使用量。当 redis 主库内存超出限制时,命令处理将会触发数据淘汰机制,淘汰(key-value)数据,直至当前内存使用量小于限制阈值。


1. 数据淘汰策略概述

redis.conf

配置 描述
maxmemory 将内存使用限制设置为指定的字节数。

redis 申请和回收内存基本上都是通过 zmalloc 接口统一管理的,可以通过接口统计 redis 的内存使用量。当 redis 超出了内存的使用限制 maxmemory,服务在处理命令时会触发 redis 内部的数据淘汰机制。淘汰目标数据一共有两种:

  1. 数据库所有(key-value)数据。
  2. 数据库所有被设置了过期时间的(key-value)数据。

aof 缓存,主从同步的积压缓冲区这些数据是不会被淘汰的,也没有计算在 maxmemory 里面。

针对这两种目标数据,它有几种淘汰策略:

  1. 随机淘汰。
  2. 先淘汰到期或快到期数据。
  3. 近似 LRU 算法(最近最少使用)
  4. 近似 LFU 算法 (最近使用频率最少)

关于近似的 lru 和 lfu 淘汰策略,英文好的朋友,可以去看看 antirez 的这两篇文章: Using Redis as an LRU cache, Random notes on improving the Redis LRU algorithm ,redis.conf 也有不少阐述。再结合源码,基本能理解它们的实现思路。


maxmemory 核心数据淘汰策略在函数 freeMemoryIfNeeded 中,可以仔细阅读这个函数的源码。


2. 配置

当 redis.conf 配置了 maxmemory,可以根据配置采用相应的数据淘汰策略。volatile-xxx 这种类型配置,都是只淘汰设置了过期时间的数据,allkeys-xxx 淘汰数据库所有数据。如果 redis 在你的应用场景中,只是作为缓存,任何数据都可以淘汰,可以设置 allkeys-xxx

配置 描述
noeviction 不要淘汰任何数据,大部分写操作会返回错误。
volatile-random 随机删除设置了过期时间的键。
allkeys-random 删除随机键,任何键。
volatile-ttl 删除最接近到期​​时间(较小的TTL)的键。
volatile-lru 使用近似的LRU淘汰数据,仅设置过期的键。
allkeys-lru 使用近似的LRU算法淘汰长时间没有使用的键。
volatile-lfu 在设置了过期时间的键中,使用近似的LFU算法淘汰使用频率比较低的键。
allkeys-lfu 使用近似的LFU算法淘汰整个数据库的键。
 
    #define MAXMEMORY_FLAG_LRU (1<<0)
    #define MAXMEMORY_FLAG_LFU (1<<1)
    #define MAXMEMORY_FLAG_ALLKEYS (1<<2)
    
    #define MAXMEMORY_VOLATILE_LRU ((0<<8)|MAXMEMORY_FLAG_LRU)
    #define MAXMEMORY_VOLATILE_LFU ((1<<8)|MAXMEMORY_FLAG_LFU)
    #define MAXMEMORY_VOLATILE_TTL (2<<8)
    #define MAXMEMORY_VOLATILE_RANDOM (3<<8)
    #define MAXMEMORY_ALLKEYS_LRU ((4<<8)|MAXMEMORY_FLAG_LRU|MAXMEMORY_FLAG_ALLKEYS)
    #define MAXMEMORY_ALLKEYS_LFU ((5<<8)|MAXMEMORY_FLAG_LFU|MAXMEMORY_FLAG_ALLKEYS)
    #define MAXMEMORY_ALLKEYS_RANDOM ((6<<8)|MAXMEMORY_FLAG_ALLKEYS)
    #define MAXMEMORY_NO_EVICTION (7<<8)

3. 数据淘汰时机

在事件循环处理命令时触发检查

 
    int processCommand(client *c) {
        ...
        if (server.maxmemory && !server.lua_timedout) {
            int out_of_memory = freeMemoryIfNeededAndSafe() == C_ERR;
            if (server.current_client == NULL) return C_ERR;
    
            if (out_of_memory &&
                (c->cmd->flags & CMD_DENYOOM ||
                 (c->flags & CLIEN
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值