前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis 的数据清理策略详解

Redis 的数据清理策略详解

作者头像
kl博主
发布2023-11-18 13:37:45
3270
发布2023-11-18 13:37:45
举报
文章被收录于专栏:kl的专栏kl的专栏

背景

摸清 Redis 的数据清理策略,给内存使用高的被动缓存场景,在遇到内存不足时

  • 怎么做是最优解提供决策依据。?

本文整理 Redis 的数据清理策略所有代码来自 Redis version : 5.x, 不同版本的 Redis 策略可能有调整

清理策略

Redis 的清理策略,总结概括为三点,被动清理、定时清理、驱逐清理

被动清理

访问 Key 时,每次都会检查该 Key 是否已过期,如果过期则删除该 Key ,get 、scan 等指令都会触发 Key 的过期检查。

关键代码如下, expireIfNeeded (redisDb *db, robj *key) 函数会触发检查并删除

代码语言:javascript
复制
robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) {
    robj *val; if (expireIfNeeded(db,key) == 1) { /* Key expired. If we are in the context of a master, expireIfNeeded()
         * returns 0 only when the key does not exist at all, so it's safe
         * to return NULL ASAP. */ if (server.masterhost == NULL) {
            server.stat_keyspace_misses++; return NULL;
        } if (server.current_client &&
            server.current_client != server.master &&
            server.current_client->cmd &&
            server.current_client->cmd->flags & CMD_READONLY)
        {
            server.stat_keyspace_misses++; return NULL;
        }
    } val = lookupKey(db,key,flags); if (val == NULL)
        server.stat_keyspace_misses++; else server.stat_keyspace_hits++; return val;
}

定时清理

通过 serverCron 定期触发清理,可以通过 hz 参数,配置每秒执行多少次清理任务,流程如下

  • 1、Redis 配置项 hz 定义了 serverCron 任务的执行周期,默认为 10,即 CPU 空闲时每秒执行 10 次
  • ?2、每次过期 Key 清理的 timelimit 不超过 CPU 时间的 25% ,即若 hz = 1,则一次清理时间最大为 250ms,若 hz = 10,则一次清理时间最大为 25ms,计算逻辑(timelimit = 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100;)
  • ?3、清理时依次遍历所有的 db;
  • ?4、从 db 中随机取 20 个 key,判断是否过期,若过期,则逐出;
  • ?5、若有 5 个以上 key 过期,则重复步骤 4,否则遍历下一个 db;
  • ?6、在清理过程中,若达到了 timelimit 时间,退出清理过程;

关键代码如下,activeExpireCycle (int type) 会执行上述逻辑

代码语言:javascript
复制
int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
    ...
    databasesCron();
    ...
} void databasesCron(void) { /* Expire keys by random sampling. Not required for slaves
     * as master will synthesize DELs for us. */ if (server.active_expire_enabled) { if (server.masterhost == NULL) {
            activeExpireCycle(ACTIVE_EXPIRE_CYCLE_SLOW);
        } else {
            expireSlaveKeys();
        }
    }
    ...
}

驱逐清理

Redis 在命令处理函数 processCommand 会进行内存的检查和驱逐,任何命令都会出触发,包括 ping 命令。

  • 如果配置了 maxmemory ,且当前内存超过 maxmemory 时,则会执行 maxmemory_policy 筛选出需要清理的 Key,继而判断 lazyfree-lazy-eviction 是否开启来进行 Key 的同步还是异步删除。无论是同步删除还是异步删除,最后都会继续校验内存是否超限,直到内存低于 maxmemory。驱逐只会在 Master 节点进行。

maxmemory_policy 可选如下:

  • ?volatile-lru:从已设置过期时间的数据集中挑选【最近最少使用】的 Key 进行删除
  • ??volatile-ttl:从己设置过期时间的数据集中挑选【将要过期】的 Key 进行删除
  • volatile-lfu:从己设置过期时间的数据集中选择【最不常用】的 Key 进行删除
  • ?volatile-random:从己设置过期时间的数据集中【任意选择】Key 进行删除
  • ??allkeys-lru:从数据集中挑选【最近最少使用】的 Key 进行删除
  • allkeys-lfu:从数据集中【优先删除掉最不常用】的 Key
  • ??allkeys-random:从数据集中【任意选择】 Key 进行删除
  • ?no-enviction:禁止驱逐数据

如上图,6.2 后的版本支持通过逐出因子 maxmemory-eviction-tenacity 来控制逐出阻塞的时间。具体的阻塞耗时间可以通过?latency-monitor?里的?eviction-cycle、eviction-del?来观测。

关键代码如下,freeMemoryIfNeeded () 函数会执行上述逻辑

代码语言:javascript
复制
int processCommand(client *c) {
 ... if (server.maxmemory && !server.lua_timedout) { int out_of_memory =  freeMemoryIfNeededAndSafe() == C_ERR;
        ...
  }
 ...
} int freeMemoryIfNeededAndSafe(void) { if (server.lua_timedout || server.loading) return C_OK; return freeMemoryIfNeeded();
}

总结

回到开篇的背景问题,当遇到内存使用高的被动缓存场景,可用内存不足时:

  • 离线分析内存,是否存在大量【已过期】的内存来不及定时清理,此时可调大 hz 参数来加速过期内存的主动清理。hz 参数最大 500 ,不过要观察 CPU 的影响,不要因为 hz 影响读写流量
  • 如果调整 hz 还是没法及时清理已过期的内存,则可以使用 scan 指令来被动访问 key 的方式手动删除,注意执行 scan 时的 count ,同时观测 CPU 使用情况,scan 的 count 越大,CPU 消耗会越高,完成一次 sacn 删除的时间最快。为了减少对线上的影响,可以在业务低峰期,周期性的执行。
  • 通过 latency-monitor 观测 eviction-cycle、eviction-del 指标,是否因内存驱逐阻塞严重,可开启 lazyfree-lazy-eviction 来缓解阻塞,如果还是很慢,可升级内存规格
  • 可升级到 7.x 版本的 Redis ,通过 maxmemory-eviction-tenacity 参数主动控制每次驱逐的阻塞时间

参考:

  • 快手 Redis 架构演进实践_脱敏.pdf
本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-09-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 清理策略
    • 被动清理
      • 定时清理
        • 驱逐清理
        • 总结
        • 参考:
        相关产品与服务
        云数据库 Redis
        腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
        http://www.vxiaotou.com