Redis内存管理

Redis的内存管理中,有两个主要的策略:过期删除策略内存淘汰策略

过期删除策略

过期删除策略指的是可以对 key 设置一个过期时间,并将已过期的键值对删除。

一般来说,Redis中的数据都会有一个过期时间。设置过期时间有这两个好处 :

  1. 因为内存是有限的,如果没有过期时间,很容易占满内存。
  2. 对于短信验证码之类有时效性的数据,如果放在数据库中就需要自己判断是否过期,这样不但麻烦而且性能较低。

设置过期时间的方法:

  • 字符串类型:setex <key> <time> <valule> (setex == set + expire ,添加了键值对并且设置过期时间)
  • 其他类型: expire <key> <time>

查看剩余过期时间的方法: ttl <key> 、 取消过期剩余时间的方法: persist <key>

Redis如何判断过期?

Redis 通过一个叫做过期字典(可以看作是 hash 表)来保存数据过期的时间。

过期字典的键指向 Redis 数据库中的某个 key(键),过期字典的值(long类型)是 key 所指向的数据库键的过期时间。

在 redisDb 结构中,数据结构如下:

1
2
3
4
5
6
7
8
typedef struct redisDb {
...

dict *dict; //数据库键空间,保存着数据库中所有键值对
dict *expires // 过期字典,保存着键的过期时间
...
} redisDb;

Redis过期删除策略?

Redis的过期删除策略为 : 【惰性删除 + 定期删除】

  • 惰性删除

    只会在取出 key 的时候才对数据进行过期检查。

    优点对 CPU 最友好,缺点是可能会造成太多过期 key 没有被删除。

  • 定期删除

    每隔一段时间抽取一批 key 执行删除过期 key 操作。并且,Redis 底层会通过限制删除操作执行的时长和频率来减少删除操作对 CPU 时间的影响。

    优点是相比惰性删除,对内存更友好。缺点是难以确定删除操作执行的时长和频率(太频繁对CPU不好,太稀疏又对内存效果不好)。

    默认定期时间为10s,可在redis.conf.hz中进行配置。默认抽查数量为20。

注意:还有一种删除策略是 定时删除。指在设置 key 的过期时间时,同时创建一个定时事件,当时间到达时,由事件处理器自动执行 key 的删除操作。这样对内存消耗太大,redis没有采用。

内存淘汰机制

如果只使用过期删除策略,仅仅通过给 key 设置过期时间还是有问题的。因为还是可能存在定期删除和惰性删除漏掉了很多过期 key 的情况。这样就导致大量过期 key 堆积在内存里,然后就 Out of memory 了。所以当 Redis 的运行内存已经超过 Redis 设置的最大内存之后,则会使用内存淘汰策略删除符合条件的 key,以此来保障 Redis 高效的运行。

Redis内存淘汰策略

Redis 提供 8 种数据淘汰策略,volatile开头的都是在过期数据中(server.db[i].expires)中淘汰,allkeys开头的都是在所有数据(server.db[i].dict)中淘汰。

  1. volatile-random:随机选择数据淘汰。
  2. volatile-ttl:优先淘汰更早过期的键值。
  3. volatile-lru(least recently used):挑选最久没使用的数据淘汰。
  4. volatile-lfu(least frequently used):最不经常使用的数据淘汰。(默认策略)
  5. allkeys-random:从数据集中任意选择数据淘汰。
  6. allkeys-lru(least recently used):挑选最久没使用的数据淘汰。
  7. allkeys-lfu(least frequently used):最不经常使用的数据淘汰。
  8. no-eviction:(不进行淘汰)禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。

查看淘汰策略:config get maxmemory-policy ,修改淘汰策略 : config set maxmemory-policy <策略>或 在配置文件中设置maxmemory-policy <策略>