`
blueswind8306
  • 浏览: 127259 次
  • 来自: ...
社区版块
存档分类
最新评论

redis的过期淘汰策略

阅读更多
最近线上遇到Redis内存达到maxmemory限制后,数据淘汰过慢导致拖慢应用请求的问题。后来仔细看了一下Redis的各种数据淘汰策略,总结一下。

首先,Redis有三种删除key的时机,它们对应不同的淘汰策略:
  • 当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key。
  • 由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动淘汰一批已过期的key。
  • 当前已用内存超过maxmemory限定时,触发主动清理策略。


下面详细说一下定期主动淘汰策略和主动清理策略,以及它们所对应的配置参数的含义。

定期主动淘汰策略
首先,这里的“定期”指的是Redis定期调用databasesCron()函数时触发的清理策略,这个定期的频率由配置文件中的hz参数决定,代表了一秒钟内,后台任务期望被调用的次数。Redis-3.0.0中的默认值是10,代表每秒钟调用10次后台任务。

hz调大将会提高Redis主动淘汰的频率,如果你的Redis存储中包含很多冷数据占用内存过大的话,可以考虑将这个值调大,但Redis作者建议这个值不要超过100。我们实际线上将这个值调大到100,观察到CPU会增加2%左右,但对冷数据的内存释放速度确实有明显的提高(通过观察keyspace个数和used_memory大小)。

除了主动淘汰的频率外,Redis对每次淘汰任务执行的最大时长也有一个限定,这样保证了每次主动淘汰不会过多阻塞应用请求,以下是这个限定计算公式:
#define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25 /* CPU max % for keys collection */
...
timelimit = 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100;

可以看出timelimit和server.hz是一个倒数的关系,也就是说hz配置越大,timelimit就越小。换句话说是每秒钟期望的主动淘汰频率越高,则每次淘汰最长占用时间就越短。这里每秒钟的最长淘汰占用时间是固定的250ms(1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/100),而淘汰频率和每次淘汰的最长时间是通过hz参数控制的。

具体的淘汰过程为:在redis.c/activeExpireCycle()函数中,针对每个db有一个循环,每次从db->expires集合中随机取出20个key,如果有超过5个key过期淘汰,则继续循环。也就是说如果超过25%的key过期淘汰,则继续淘汰,直到随机抽取的key的过期率低于25%,或者整个循环时间超过timelimit的最大限定。则结束整个淘汰过程。

从以上的分析看,当redis中的过期key比率没有超过25%之前,提高hz可以明显提高扫描key的最小个数。假设hz为10,则一秒内最少扫描200个key(一秒调用10次*每次最少随机取出20个key),如果hz改为100,则一秒内最少扫描2000个key;另一方面,如果过期key比率超过25%,则扫描key的个数无上限,但是cpu时间每秒钟最多占用250ms。

maxmemory的主动清理策略
当mem_used内存已经超过maxmemory的设定,对于所有的读写请求,都会触发redis.c/freeMemoryIfNeeded(void)函数以清理超出的内存。注意这个清理过程是阻塞的,直到清理出足够的内存空间。所以如果在达到maxmemory并且调用方还在不断写入的情况下,可能会反复触发主动清理策略,导致请求会有一定的延迟。

清理时会根据用户配置的maxmemory-policy来做适当的清理(一般是LRU或TTL),这里的LRU或TTL策略并不是针对redis的所有key,而是以配置文件中的maxmemory-samples个key作为样本池进行抽样清理。

maxmemory-samples在redis-3.0.0中的默认配置为5,如果增加,会提高LRU或TTL的精准度,redis作者测试的结果是当这个配置为10时已经非常接近全量LRU的精准度了,并且增加maxmemory-samples会导致在主动清理时消耗更多的CPU时间。


建议:
  • 尽量不要触发maxmemory,最好在mem_used内存占用达到maxmemory的一定比例后,需要考虑调大hz以加快淘汰,或者进行集群扩容。
  • 如果能够控制住内存,则可以不用修改maxmemory-samples配置;如果Redis本身就作为LRU cache服务(这种服务一般长时间处于maxmemory状态,由Redis自动做LRU淘汰),可以适当调大maxmemory-samples。



以下是上文中提到的配置参数的说明:

hz参数:
# Redis calls an internal function to perform many background tasks, like
# closing connections of clients in timeout, purging expired keys that are
# never requested, and so forth.
#
# Not all tasks are performed with the same frequency, but Redis checks for
# tasks to perform according to the specified "hz" value.
#
# By default "hz" is set to 10. Raising the value will use more CPU when
# Redis is idle, but at the same time will make Redis more responsive when
# there are many keys expiring at the same time, and timeouts may be
# handled with more precision.
#
# The range is between 1 and 500, however a value over 100 is usually not
# a good idea. Most users should use the default of 10 and raise this up to
# 100 only in environments where very low latency is required.
hz 10


maxmemory-policy的清理策略:
# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> remove the key with an expire set using an LRU algorithm
# allkeys-lru -> remove any key according to the LRU algorithm
# volatile-random -> remove a random key with an expire set
# allkeys-random -> remove a random key, any key
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
# noeviction -> don't expire at all, just return an error on write operations
#
# Note: with any of the above policies, Redis will return an error on write
#       operations, when there are no suitable keys for eviction.
#
#       At the date of writing these commands are: set setnx setex append
#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#       getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy noeviction


maxmemory-samples抽样清理的个数:
# LRU and minimal TTL algorithms are not precise algorithms but approximated
# algorithms (in order to save memory), so you can tune it for speed or
# accuracy. For default Redis will check five keys and pick the one that was
# used less recently, you can change the sample size using the following
# configuration directive.
#
# The default of 5 produces good enough results. 10 Approximates very closely
# true LRU but costs a bit more CPU. 3 is very fast but not very accurate.
#
# maxmemory-samples 5
分享到:
评论

相关推荐

    面试官:Redis 过期删除策略和内存淘汰策略有什么区别?.doc

    Redis 过期删除策略和内存淘汰策略的区别 Redis 是一个高效的 NoSQL 数据库,可以对 key 设置过期时间,以便删除已过期的键值对。然而,Redis 还有一个内存淘汰策略,用于删除 Redis 中的键值对以释放内存。那么,...

    22_redis的过期策略能介绍一下?要不你再手写一个LRU?.zip

    LRU算法则是常见的内存淘汰策略,当缓存满时,根据最近最少使用的数据进行淘汰。 Redis提供了多种过期策略,包括: 1. **定时过期(Timing Expire)**:在设置键的过期时间时,Redis会创建一个定时器,当到达指定...

    redis过期策略和内存淘汰机制.pdf

    "Redis过期策略和内存淘汰机制" Redis是一种基于内存的NoSQL数据库,它具有高效的读写性能和丰富的数据结构。但是,Redis的内存使用量也会不断增加,如果不进行合理的内存管理,将会导致Redis服务器崩溃或性能下降...

    关于redis Key淘汰策略的实现方法

    在 Redis 中,当内存使用达到预设的最大值(`maxmemory`)时,为了保持内存占用在可控范围内,Redis 提供了多种键淘汰策略。这些策略用于决定在内存不足时哪些键应该被删除,以便为新数据腾出空间。本文将详细介绍 ...

    浅谈redis的maxmemory设置以及淘汰策略

    关于redis的淘汰策略: Redis提供了下面几种淘汰策略供用户选择,其中默认的策略为noeviction策略: · noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错。 · allkeys-lru:在主键空间中,...

    Redis过期-淘汰机制的解析和内存占用过高的解决方案.docx

    在 Redis 中,淘汰策略包括 volatile-lru、allkeys-lru、volatile-lfu、allkeys-lfu、volatile-random 和 allkeys-random 等。这些策略可以根据不同的场景和需求进行选择和配置。 Redis 过期-淘汰机制是非常重要的...

    Redis 服务等过期策略和内存淘汰策略解析

    Redis 服务等过期策略和内存淘汰策略解析

    redis的缓存失效策略和主键失效机制【java面试常问】.docx

    随着业务的增长,Redis的内存占用逐渐逼近1GB,此时根据预先配置的数据淘汰策略,Redis将自动开始淘汰数据以避免内存溢出。 - 如果采用的是`volatile-lru`策略,Redis将首先从设置了过期时间的数据集中查找并淘汰...

    Redis清理过期key的方法.doc

    Redis 提供了六种淘汰策略:noeviction、allkeys-random、allkeys-lru、allkeys-lfu、volatile-random、volatile-lru、volatile-ttl、volatile-lfu。 其中,noeviction 是 Redis 的默认配置,它不会删除任何 key,...

    redis如何删除过期数据.rar

    5. **内存优化**:当 Redis 内存达到 `maxmemory` 配置限制时,根据所选的内存淘汰策略,Redis 会自动删除部分键以释放空间。过期键会被优先考虑。 6. **AOF 重写与过期数据**:在进行 AOF (Append Only File) 重写...

    redis缓存过期设置1

    为了有效地处理内存使用,Redis 提供了多种策略来处理缓存过期和移除。这里我们将深入探讨标题和描述中提到的几种缓存过期策略: 1. **volatile-lru**: 这是 Redis 默认的过期策略之一。当内存空间不足时,它会...

    springboot分布式自增id_javaredis_源码

    当内存压力大时,Redis会触发淘汰策略,这里描述的是近似LRU策略。Redis并不是为每个键存储访问时间,而是使用一个小的随机样本,根据键的TTL判断其可能的最近访问时间。 4. **LRU(Least Recently Used)**:LRU...

    Redis硬核性能优化

    4. 实例内存达到上限:内存不足会触发Redis的淘汰策略,增加额外开销。 5. fork耗时严重:主进程复制子进程进行持久化时,可能导致短暂的阻塞。 6. 开启内存大页:虽然能提高效率,但可能导致内存分配问题。 7. 开启...

    Redis面试题集

    Redis 的数据淘汰策略包括 noeviction(禁止淘汰)、allkeys-lru(回收最少使用的键)、volatile-lru(回收过期集合中最少使用的键)、allkeys-random(回收随机键)、volatile-random(回收过期集合中随机键)、...

    redis面试题及其答案.pdf

    Redis还有多种数据淘汰策略,可以根据是否设置了数据过期时间以及数据集的大小进行不同策略的选择。例如,volatile-lru策略是从已设置过期时间的数据集中挑选最近最少使用的数据进行淘汰,而allkeys-lru则是从所有...

Global site tag (gtag.js) - Google Analytics