您的位置:首页 > 数据库 > Redis

redis随笔(二)----淘汰策略的原理以及实现

2017-08-30 16:13 681 查看
1 配置文件中的最大内存删除策略

在redis的配置文件中,可以设置redis内存使用的最大值,当redis使用内存达到最大值时(如何知道已达到最大值?),redis会根据配置文件中的策略选取要删除的key,并删除这些key-value的值。若根据配置的策略,没有符合策略的key,也就是说内存已经容不下新的key-value了,但此时有不能删除key,那么这时候写的话,将会出现写错误。

1.1 最大内存参数设置

若maxmemory参数设置为0,则分两种情况:

*在64位系统上,表示没有限制。

*在32为系统上,是3G,redis官方文档的说法是,32位系统最大内存是4G,预留1G给系统。而且策略会自动设置为noeviction。

也就是说在32位系统上,若maxmemory设置为0,则默认是3G,当到达3G,再往reidis中写入时,则会报错。

1.2 到达最大内存时的几种删除key的策略

* volatile-lru -> remove the key with an expire set using an LRU algorithm

按照LRU算法(最少最近没使用)来选取,并删除已经设置了expire时间的key。

* allkeys-lru -> remove any key accordingly to the LRU algorithm

根据LRU算法,删除任意的key。不论这个key是否设置了expire时间。

* volatile-random -> remove a random key with an expire set

随机删除一个设置了expire时间的key。

* allkeys-random -> remove a random key, any key

随机删除任意一个key,不论这个key是否设置了expire时间。

* volatile-ttl -> remove the key with the nearest expire time (minor TTL)

删除具有最近终止时间值(TTL)的key。

* noeviction -> don't expire at all, just return an error on write operations

若没有设置终止时间,返回一个错误。

1.3 配置内存最大值策略

以下这些命令的默认策略是:volatile-lru

# At the date of writing this 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 volatile-lru

1.4 配置要删除key的检测样本个数

maxmemory-samples

由于LRU和最小TTL算法都是不是精确的算法。因此你可以选择要检测样本的个数。例如,默认情况下redis将会检查3个key,并从这3个key中选取一个最近没有使用的key。当然你可以修改检查样本的个数的值。

要修改这个值,可以通过在配置文件中设置参数:

maxmemory-samples 3

2 实现

这几种删除策略的实现都是在函数 freeMemoryIfNeeded(void) 中完成的。下面具体讲解每种策略是如何实现的。

2.1 什么时候去删除key-value

当设置了maxmemory-policy策略后,什么时候会去删除key呢?

实际上,当设置了maxmemory参数后,在处理每个命令的时候都会根据maxmemory-policy去删除对应的key值。

代码如下:

?
实战1:若没有设置maxmemory变量,即使设置了maxmemory-policy,也不会起作用。

实战2:若没有设置maxmemory变量,在处理命令时将不会调用释放策略,会加速命令的处理过程。

2.2 删除key的总体流程

当内存达到最大值时需要按策略删除老的key,所有的删除操作和删除策略的实现都是在函数freeMemoryIfNeeded()中实现的。

在执行删除策略之前,先要选取db和查找key。

总体步骤如下:

?
2.2 volatile-lru机制和allkeys-lru的实现

2.2.1 redis中的LRU机制

对于LRU机制,redis的官方文档有这样的解释:

?
大意是说,redis的LRU算法不是正真意思上的LRU。而是使用另外一种方式实现的。也就意味着,redis并不能每次都选择一个最好的key来删除。没有使用正真的LRU算法的原因是,它可能会消耗更多的内存。该算法和正真的LRU算法效果大概相同。

redis是在一小部分key中选择最优的要删除的key。这一小部分key的个数可以指定,可以在配置文件中设置参数maxmemory-samples 。

2.2.2 LRU机制的实现

freeMemoryIfNeeded()函数,首先要计算最大空余内存和目前已经使用的内存大差值,若不够了,就要释放老的key-value。

若使用的是LRU策略,就会走以下代码,先进行最优删除key的选择,然后进行删除操作:

?
以上这篇关于redis Key淘汰策略的实现方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: