十、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进行删除。
相关推荐
DKPT4 分钟前
如何确定MySQL中哪些列适合做索引
数据库·spring boot·spring·spring cloud·缓存
wilsonzane21 分钟前
Mongodb集群中的分布式读写
数据库·分布式·mongodb
关中雪30 分钟前
【应届应知应会】SQL常用知识点50道
数据库·mysql·nosql·秋招·校招·春招
zxrhhm41 分钟前
MySQL中使用PROFILING来查看SQL执行流程
数据库·mysql
醇氧41 分钟前
【postgresql】表操作
数据库·sql·postgresql
PGCCC42 分钟前
使用预加载库优化 PostgreSQL 函数#postgresql认证
数据库·postgresql
baozongwi1 小时前
CTF常用sql注入(一)联合注入和宽字节
数据库·sql·web安全
freesharer1 小时前
Zabbix 配置WEB监控
前端·数据库·zabbix
尾巴尖上的阳光2 小时前
ETCD概述--使用/特性/架构/原理
数据库·架构·etcd
关兮月2 小时前
MySQL存储与优化 一、MySQL架构原理
数据库·mysql