当Redis内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换。交换会让Redis的性能急剧下降,对于访问量比较频繁的Redis来说等于不可用。
为了限制最大使用内存,Redis提供了配置参数maxmemory来限制内存超出期望大小。当实际内存超出maxmemory时,Redis 提供了几种可选策略来让用户自己决定该如何腾出新的空间以继续提供读写服务:
1.noeviction不会继续服务写请求 (DEL请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能持续进行。这是默认的淘汰策略。
我们知道,redis设置配置文件的maxmemory参数,可以控制其最大可用内存大小(字节)。
那么当所需内存,超过maxmemory怎么办?
这个时候就该配置文件中的maxmemory-policy出场了。
其默认值是noeviction。
下面我将列出当可用内存不足时,删除redis键具有的淘汰规则。
规则名称 | 规则说明 |
---|---|
noeviction | 不删除键,只返回错误 |
volatile-lru | 使用LRU算法删除一个键(只对设置了生存时间的键) |
allkeys-lru | 使用LRU算法删除一个键 |
volatile-random | 随机删除一个键(只对设置了生存时间的键) |
allkeys-random | 随机删除一个键 |
volatile-ttl | 删除生存时间最近的一个键 |
LRU算法,least Recently Used,最近最少使用算法。也就是说默认删除最近最少使用的键。
但是一定要注意一点!redis中并不会准确的删除所有键中最近最少使用的键,而是随机抽取3个键,删除这三个键中最近最少使用的键。
那么3这个数字也是可以设置的,对应位置是配置文件中的maxmeory-samples.
Redis是怎么设计这个策略的呢?
答:Redis给每个key增加了一个额外的小字段,这个字段的长度是24个 bit,也就是最后一次被访问的时间戳。
Redis采取了近似于LRU算法,采用懒惰处理方式,当发现内存超出maxmemory,就会执行一次LRU淘汰算法。就是随机采样出5(可以配置)个key,然后淘汰掉最旧的key,如果淘汰后内存还是超出maxmemory,那就继续随机采样淘汰,直到内存低于maxmemory为止。
如何采样就是看 maxmemory-policy 的配置,如果是allkeys就是从所有的key字典中随机,如果是volatile就从带过期时间的 key 字典中随机。每次采样多少个key看的是 maxmemory_samples的配置,默认为5。
同时 Redis3.0在算法中增加了淘汰池,进一步提升了近似 LRU 算法的效果。淘汰池是一个数组,它的大小是maxmemory_samples,在每一次淘汰循环中,新随机出来的key列表会和淘汰池中的key 列表进行融合,淘汰掉最旧的一个key之后,保留剩余较旧的key列表放入淘汰池中留待下一个循环。