十、Redis内存回收策略和机制

1、Redis的内存回收

Redis中可以设置key的过期时间,以期可以让Redis回收内存,循环使用。在Redis中有4个命令可以设置Key的过期时间。分别为 expirepexpireexpireatpexpireat

1.1、expire

expire key ttl:将key的过期时间设置为ttl秒。

1.2、pexpire

pexpire key ttl:将key的过期时间设置为ttl毫秒。

1.3、expireat

expireat key timestamp:将key的过期时间设置为指定的timestamp(时间戳,秒)。

1.4、pexpireat

pexpireat key timestamp:将key的过期时间设置为指定的timestamp(时间戳,毫秒)。

PS:不论使用的是哪个命令。 Redis最终都是使用pexpireat命令实现。

1.5、ttl

ttl key:查看key剩余过期时间(秒)

1.6、pttl

pttl key:查看key的剩余过期时间(毫秒)

PS:如果未设置过期时间,则返回-1,如果key不存在,则都返回-2。

RedisDb结构体定义:

c 复制代码
typedf struct redisDb{
	dict *dict;  //数据库的键空间,保存数据库中的所有键值对
    dict *expires;  //保存所有过期的键
    dict *blocking_keys;   //keys for clients waiting for data(blpop)
    dict *ready_keys;   //Blocked keys that received PUSH
    dict *watched_Keys;   //watched keys for multi/exec cas
    int id;   //数据库ID字段,代表不同的数据库
    long long avg_ttl;   //average TTL, just for stats
}redisDb;

2、Redis的过期策略

2.1、定时删除

为每个key创建一个定时任务,一旦到达过期时间,就立即删除。该策略可以立即清除掉过期的key,对内存友好,但是对CPU不友好,回影响Redis的吞吐量和响应时间。

2.2、惰性删除

当访问一个key时,才判断这个key是否过期,如果过期的话,就删除。该策略能最大的节省CPU的资源。但是对内存不是很友好,极端情况下,可能存在大量的key已经过期,但是由于在过期后就没有被访问过,导致无法被删除。

2.3、定期删除

每个一段时间,扫描Redis中过期key字典(expires),并清除部分过期的key。该策略是前两者的一个折中方案,可以通过调整定时扫描的时间时间和每次扫描的限定耗时,在不同情况下使得CPU和内存资源达到最优平衡。

在Redis中,同时使用了惰性删除和定期删除。

3、Redis淘汰策略

Redis的内存淘汰策略,是指内存达到maxmemory极限时,使用某种算法来决定清理掉哪些数据,以保证新数据的写入。

3.1、Redis的内存淘汰机制

  • no-eviction:当内存不足写入新数据时,新写入操作会报错。
  • allkeys-lru:当内存不足以写入新数据时,在所有的key中,采用LRU算法删除最近最少使用的key。
  • allkeys-random:当内存不足以写入新数据时,在所有的key中,随机删除某个key。
  • volatile-lru:当内存不足以写入新数据时,在设置了过期时间的key中,采用lru算法删除最近最少使用的key。
  • volatile-random:当内存不足以写入新数据时,在设置了过期时间的key中,随机删除某个key。
  • volatile-ttl:当内存不足以写入新数据时,在设置了过期时间的key中,删除最快过期的key删除。
  • volatile-lfu:当内存不足以写入新数据时,在设置了过期时间的key中,删除使用频率最少的的key。
  • allkeys-lfu:当内存不足以写入新数据时,在所有的key中,采用lfu算法删除使用频率最少的key。

3.2、LRU算法-标准实现

标准的LRU实现方式:

  1. 添加新的数据时,会将新数据放到链表的头部。
  2. 当数据被访问时,被访问的数据会被放到链表的头部。
  3. 当链表满时,会将链表尾部的数据删除。

正常的LRU算法的实现是采用Map+双向链表的方式实现的。也即是在访问数据时,先使用map判断下是否存在,如果存在,则将被访问的数据移动到链表的头部。如果添加数据,会现在链表的头部添加,成功之后,在放到map中。

3.3、LRU算法-Redis实现

Redis中的LRU算法并不是标准的LRU算法,而是一种近似LRU算法。在Redis3.0之前,Redis是随机取出若干个key(默认是5个,可以通过maxmemory-samples配置),然后删除取出key中最久被访问的那个key。

Redis3.0之后,改进了LRU算法的实现,采用维护一个回收候选键池的方式。

  1. 首先,第一次随机取的key会被放到一个pool中(pool的大小为16),pool中的key是按照key的最近访问的时间排序的(lru)。接下来每次随机取的key,lru值都必须小于pool中最小的lru才能被继续放入。放满之后,每次如果有新的key需要放入,需要将pool中lru最大的一个key取出。
  2. 淘汰的时候,直接从pool中选出一个lru最小的key进行删除。
相关推荐
dingdingfish4 小时前
Oracle 数据库 IDENTITY 列
sql·oracle·column·database·developer·identity·12c
呆呆小雅4 小时前
C# 可空类型
数据库·oracle·c#
Duck Bro5 小时前
MySQL:常用数据类型
java·数据库·c++·mysql·java-ee
z千鑫5 小时前
【C/C++】数据库链接入门教程:从零开始的详细指南!MySQL集成与操作
c语言·数据库·c++
开敲5 小时前
【MySQL】MySQL数据库基础
数据库·mysql
痞老板A小安装C45 小时前
Redis 过期策略和内存淘汰策略
数据库·redis·缓存
陈燚_重生之又为程序员7 小时前
梧桐数据库的高效索引技术分析
数据库
hellolio7 小时前
PostgreSQL详细安装教程
数据库·postgresql
鳄鱼的眼泪18 小时前
mysql深度分页优化
数据库·mysql
yava_free8 小时前
介绍一下mysql binlog查看指定数据库的方法
java·数据库·mysql