Redis内存淘汰策略详解
1、为什么需要淘汰策略
我们都知道Redis是⼀个基于k-v数据库,随着⾥⾯键值对的增加,redis内存的使⽤量也会上升,因此,我们需要对Redis的最⼤内存使⽤量进⾏限制。那么有了Redis的内存容量限制,那么就会有达到这个内存容量限制的时候,这个时候就需要对Redis存储的数据进⾏清理,释放内存,将Redis内存使⽤量保持在容量限制以下,淘汰数据的策略当然不是盲⽬的,是有策略的因此需要内存淘汰策略。
2、Redis中的max-memory
在64位的系统中,Redis是没有对内存容量做限制的,但是在32位系统中默认内存容量的默认值是3GB,以下是官⽅原话
Setting maxmemory to zero results into no memory limits. This is the default behavior for 64 bit systems, while 32 bit systems use an implicit memory limit of 3GB.
max-memory可以在f中进⾏添加设置
max-memory 300mb
也可以在运⾏时使⽤命令CONFIG SET动态设置
CONFIG SET max-memory 300mb
3、淘汰内存的过程
官⽅原话
1、A client runs a new command, resulting in more data added.
2、Redis checks the memory usage, and if it is greater than the maxmemory limit , it evicts keys according to the policy.
3、A new command is executed, and so forth.
1、客户端执⾏⼀个新指令,添加数据
2、Redis检查内存使⽤量,如果⼤于maxmemory限制,就通过淘汰策略清理内存
3、执⾏新命令,重复上述过程
4、Redis中的内存淘汰策略
1、noeviction:添加数据时,如果redis判断该操作会导致占⽤内存⼤⼩超过内存限制,就返回error,然后啥也不⼲
2、allkeys-lru:添加数据时,如果redis判断该操作会导致占⽤内存⼤⼩超过内存限制,就会扫描所有的key,淘汰⼀些最近未使⽤的
key
3、volatile-lru:添加数据时,如果redis判断该操作会导致占⽤内存⼤⼩超过内存限制,扫描那些设置⾥过期时间的key,淘汰⼀些最
近未使⽤的key
4、allkeys-random:添加数据时,如果redis判断该操作会导致占⽤内存⼤⼩超过内存限制,就会扫描所有的key,随机淘汰⼀些key
5、volatile-random:添加数据时,如果redis判断该操作会导致占⽤内存⼤⼩超过内存限制,扫描那些设置⾥过期时间的key,随机淘
汰⼀些key
6、volatile-ttl:添加数据时,如果redis判断该操作会导致占⽤内存⼤⼩超过内存限制,扫描那些设置⾥过期时间的key,淘汰⼀些即
将过期的key
7、volatile-lfu:添加数据时,如果redis判断该操作会导致占⽤内存⼤⼩超过内存限制,就会淘汰⼀些设置了过期时间的,并且最近最
access被淘汰了吗少使⽤的key
8、allkeys-lfu:添加数据时,如果redis判断该操作会导致占⽤内存⼤⼩超过内存限制,就会扫描所有的key,淘汰⼀些最近最少使⽤
的key
5、Redis中实现的LRU算法为近似算法
为什么说Redis实现的LRU算法是近似算法呢,官⽅⽂档有提到
Redis LRU algorithm is not an exact implementation. This means that Redis is not able to pick the be
st candidate for eviction, that is, the access that was accessed the most in the past. Instead it will try to run an approximation of the LRU algorithm, by sampling a small number of keys, and evicting the one that is the best (with the oldest access time) among the sampled keys.
However since Redis 3.0 the algorithm was improved to also take a pool of good candidates for eviction. This
improved the performance of the algorithm, making it able to approximate more closely the behavior of a real LRU algorithm.
What is important about the Redis LRU algorithm is that you are able to tune the precision of the algorithm by changing the number of samples to check for every eviction. This parameter is controlled by the following
configuration directive
以上阐述了以下观点
1、Redis中实现的LRU算法是近似算法,它是通过抽样的⽅式来淘汰key
2、Redis3.0以后得到了改善,该近似算法很接近原LRU算法了
3、Redis提供了⼀个参数让⽤户配置,可以使得近似LRU算法接近原LRU算法
这个参数就是maxmemory-samples
CONFIG SET maxmemory-samples <count>
通过上述指令可以设置该值,也可以在f中设置
6、Redis中的LFU算法
前⾯提到的LRU算法看似已经是⽐较好的算法了,但实际上存在⼀些缺陷,因为存在某些key,在最近被访问过后就不再访问了,⽽有些key是很久以前访问过,但是以后很可能也要访问的,如果根据LRU算法,就会导致前⼀类key保留下来,反⽽后⼀类真正需要的key就被淘汰了,因此LFU算法就是该问题的解决⽅式
LFU算法在Redis中是通过⼀个计数器来实现的,每个key都有⼀个计数器,访问频度越⾼,计数器的值就越⼤,Redis就根据计数器的值来淘汰key,当然计数器的值也是会随着时间减少的
⽤户可配置的LFU算法参数⼀共有两个分别是:lfu-log-factor和lfu-decay-time
lfu-log-factor参数值设置的越⼤,key的计数值就越难增长,因此就要求key的访问频度较⾼才能避免被淘汰
lfu-decay-time参数值是表⽰隔多久将计数器的值减⼀
下⾯是不同的factor情况下的计数值的增长情况,计数器不是每访问⼀次都会增加⼀,它是和factor有关系的,计数值的最⼤值是
255,factor越⼤,计数器的值增长就越难,如下图
1+--------+------------+------------+------------+------------+------------+
2| factor | 100 hits  | 1000 hits  | 100K hits  | 1M hits    | 10M hits  |
3+--------+------------+------------+------------+------------+------------+
4| 0      | 104        | 255        | 255        | 255        | 255        |
5+--------+------------+------------+------------+------------+------------+
6| 1      | 18        | 49        | 255        | 255        | 255        |
7+--------+------------+------------+------------+------------+------------+
8| 10    | 10        | 18        | 142        | 255        | 255        |
9+--------+------------+------------+------------+------------+------------+
10| 100    | 8          | 11        | 49        | 143        | 255        |
11+--------+------------+------------+------------+------------+------------+
7、内存淘汰策略的选择(个⼈观点)
我们在选择使⽤淘汰策略的时候可以根据访问key的⽅式来选择不同的淘汰策略
1、当我们redis中的key基本上都有⽤到,也就是说每个key都有周期性访问到,那就可以选择使⽤random策略
2、当我们redis中的key部分是我们经常访问的,部分是⾮经常访问的就可以考虑使⽤LRU和LFU策略
3、当我们想根据时间长久淘汰超时数据时,就选⽤ttl
4、我们根据我们的需要是否有要长久保存的key来选择volatile或者是all,如果有需要长久保存的key,则使⽤volatile,否则可以使⽤all全表扫描

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。