内存耗尽后redis会发生什么
内存回收
使用redis服务时,很多情况下某些简直对只会在特定的时间内有效,为了防止这种类型的数据一直占用内存,我们可以给键值对设置有效期,Redis可以通过四个独立的命令来给一个键设置一个过期时间:
- ,expire key ttl:将key值的过期时间设置为ttl秒;
- pexpire key ttl:将key值的过期时间设置为ttl毫秒;
- expireat key timestamp:将key 值的过期时间设置为指定的timestamp;
- pexpireat key timestamp:将key值的过期时间设置为指定的timestamp毫秒数;
不管是那个命令,最终redis底层都是使用pexpireat命令来实现的。set 命令可以在设置key的同时加上过期时间,这样可以保证设值和设过期时间的原子性;
设置过期时间后,可以通过ttl和pttl两个命令来查询剩余过期时间如果未设置过期时间,则返回-1,如果设置了非法的过期时间,在都返回-2;
- ttl key 返回过期时间
- pttl key 返回key剩余过期的毫秒数据
过期策略
如果将一个过期的键删除,我们一般都会有三种策略:
- 定时删除:为每个键设置一个定时器,一旦过期时间道理,则将键删除。这种策略对内存很友好,但是对cpu不友好,因为每个定时器都会占用一定的cou资源;
- 惰性删除:不管键有没有过期都不主动删除,等到每次去获取键是在判断是哦福过期,如果过期就删除该键,否则返回键对应的值,这种策略对内存不够友好,可能会浪费很多内存;
- 定期扫描:系统每个一段时间就定期扫描一次 ,发现过期的键就进行删除。这种策略相对来说是对上面两种策略的折中,缺陷就是可能会出现已经过期的键也被返回;
在Redis当中,其选择的是策略2和策略3的综合使用,不过redis的定期扫描指挥扫描设置了过期时间的键,因为设置了过期时间的键Redis会单独存储,所i一不会扫描所有键;
typedef struct redisDb {
dict *dict; //所有的键值对
dict *expires; //设置了过期时间的键值对
dict *blocking_keys; //被阻塞的key,如客户端执行BLPOP等阻塞指令时
dict *watched_keys; //WATCHED keys
int id; //Database ID
//... 省略了其他属性
} redisDb;
8种淘汰策略
假如Redis中所有的教案都没有过期,而且此时内存满了,那么客户端继续执行set等命令时redis会怎么处理呢?
首先redis提供一个参数maxmemory来配置redis最大使用内存;
maxmemory
或者也可以使用config set maxmemory 1GB来动态修改。
如果没有设置该参数,那么在32位的操作系统中redis最多使用3GB内存,而在64位的操作系统中则不做限制;
redis中提供了8种淘汰策略,可以通过参数maxmemory-policy进行配置;
PS:淘汰策略也可以直接使用命令 config set maxmemory-policy <策略> 来进行动态配置。