Redis数据淘汰策略设置
知识兔用的是宝塔面板默认安装的redis。默认安装后Redis数据淘汰策略是noeviction,它在redis可使用最大内存满了之后会直接给返回错误。下面说下如何更改这项设置。
本文目录
1.连接redis
先是正常SSH远程连接服务器。
cd进入redis安装目录
cd /www/server/redis
运行redis客户端
redis-cli
2.查看默认策略
我们在设置前,先看一下现在的策略设置是什么
config get maxmemory-policy
可以看到现在是默认的noeviction策略。
3.修改Redis数据淘汰策略
这里修改一般是2种方式,知识兔建议使用第一种修改配置文件的方式。
3.1修改配置文件
修改redis配置文件,宝塔redis大约在599行。
去掉前面#号,后面noeviction修改为allkeys-lru。
修改后如下:
修改后记得点击下面的保存,然后知识兔重启Redis。
3.2通过命令设置
我们也可以试用下面命令来设置数据淘汰策略。
config set maxmemory-policy allkeys-lru
同样这里修改后我们重启一下redis。
修改策略并重启redis后我们可以使用config get maxmemory-policy命令查看现在的数据淘汰策略。
其他内容
Redis 4.0之前默认有6种数据淘汰策略。
1.noeviction(默认策略):对于写请求不再分享服务,直接返回错误(DEL请求和部分特殊请求除外)2.allkeys-lru:从所有key中使用LRU算法进行淘汰(LRU算法:即最近最少使用算法)3.volatile-lru:从设置了过期时间的key中使用LRU算法进行淘汰4.allkeys-random:从所有key中随机淘汰数据5.volatile-random:从设置了过期时间的key中随机淘汰6.volatile-ttl:在设置了过期时间的key中,淘汰过期时间剩余最短的当使用volatile-lru、volatile-random、volatile-ttl这三种策略时,如果知识兔没有key可以被淘汰,则和noeviction一样返回错误
关于Redis的淘汰策略可以查看文章:https://www.cnblogs.com/frankyou/p/16283974.html
知识兔防删备份文章(原样保存):
Redis 内存淘汰策略
实际上redis定义了【八种内存淘汰策略】来处理redis内存满的情况
noeviction:直接返回错误,不淘汰任何已经存在的redis键allkeys-lru:所有的键使用lru算法进行淘汰volatile-lru:有过期时间的使用lru算法进行淘汰allkeys-random:随机删除redis键volatile-random:随机删除有过期时间的redis键volatile-ttl:删除快过期的redis键volatile-lfu:根据lfu算法从有过期时间的键删除allkeys-lfu:根据lfu算法从所有键删除
设置多大的缓存容量合适?
具体结合应用数据实际访问特点和成本开销来综合考虑。一般建议把缓存容量设置为总数据量的 15% 到 30%,兼顾访问性能和内存空间开销。
对于 Redis 来说,一旦确定了缓存最大容量,比如 4GB,就可以执行下面命令:
CONFIG SET maxmemory4gb
不过,缓存被写满是不可避免的。
缓存替换需要解决两个问题:
- 决定淘汰哪些数据
- 如何处理那些被淘汰的数据
Redis 缓存有哪些淘汰策略?
Redis 4.0 之前一共实现了 6 种内存淘汰策略,在 4.0 之后,又增加了 2 种策略。我们可以按照是否会进行数据淘汰把它们分成两类
- 不进行数据淘汰的策略,只有 noeviction 这一种。
- 会进行淘汰的 7 种其他策略。
会进行淘汰的 7 种策略,我们可以再进一步根据淘汰候选数据集的范围把它们分成两类:
- 在设置了过期时间的数据中进行淘汰,包括 volatile-random、volatile-ttl、volatilelru、volatile-lfu(Redis 4.0 后新增)四种。
- 在所有数据范围内进行淘汰,包括 allkeys-lru、allkeys-random、allkeys-lfu(Redis 4.0 后新增)三种。
(1)默认情况下,redis在使用的内存空间超过maxmemory值时,并不会淘汰数据,也就是设置的noeviction 策略。对应到redis缓存,也就是值,一旦缓存被写满了,再有写请求到来时,redis不会分享服务,而是直接返回错误。(因此不推荐使用)
(2)对于 volatile-random、volatile-ttl、volatile-lru 和 volatile-lfu这四种淘汰策略,它们筛选的候选数据范围,被限制在已经设置了过期时间的键值对上。也正是因为如此,即使知识兔缓存没有写满,这些数据如果知识兔过期了,也会被删除。
- volatile-ttl 在筛选时,会针对设置了过期时间的键值对,知识兔根据过期时间的先后进行删除,越早过期的越先被删除。
- volatile-random 就像它的名称一样,在设置了过期时间的键值对中,进行随机删除。
- volatile-lru 会使用 LRU 算法筛选设置了过期时间的键值对。
- volatile-lfu 会使用 LFU 算法选择设置了过期时间的键值对。(LFU算法会在LRU算法的基础上,同时考虑数据的访问时效性和数据的访问次数)
(3)对于allkeys-lru、allkeys-random、allkeys-lfu这三种淘汰策略的备选淘汰数据范围,扩大到了所有键值对,无论这些键值对是否设置了过期时间。
- allkeys-random 策略,从所有键值对中随机选择并删除数据;
- allkeys-lru 策略,知识兔使用 LRU 算法在所有数据中进行筛选。
- allkeys-lfu 策略,知识兔使用 LFU 算法在所有数据中进行筛选
也就是说,如果知识兔一个键值对被删除策略选中了,即使知识兔它的过期时间还没到,也需要被删除。当然,如果知识兔它的过期时间到了但未被策略选中,同样也会被删除。
怎么使用呢?
- 优先使用allkeys-lru策略。这样,知识兔可以充分利用LRU算法的优势,把最近最常访问的数据留在缓存中,提升应用的访问性能。如果知识兔你的业务数据中有明显的冷热数据的区分,知识兔建议使用allkeys-lru策略
- 如果知识兔业务应用中的数据访问频率不大,没有明显的冷热数据区分,知识兔建议使用allkeys-random策略,随机淘汰数据即可
- 如果知识兔业务有置顶的需求,比如置顶新闻、置顶视频,那么,知识兔可以使用 volatile-lru策略,同时不给这些置顶数据设置过期时间。这样一来,这些需要置顶的数据一直不会被删除,而其他数据会在过期时根据 LRU 规则进行筛选
LRU算法
LRU 算法的全称是 Least Recently Used,从名字上就可以看出,这是按照最近最少使用的原则来筛选数据,最不常用的数据会被筛选出来,而最近频繁使用的数据会留在缓存中。
那具体是怎么筛选的呢? LRU会把所有的数据组织成一个链表,链表的头和尾分别表示MRU端和LRU段,分别代表最近最常使用的数据和最近最不常用的数据。
如下图
- 我们现在有数据 6、3、9、20、5。如果知识兔数据 20 和 3 被先后访问,它们都会从现有的链表位置移到 MRU 端,而链表中在它们之前的数据则相应地往后移一位。因为,LRU 算法选择删除数据时,都是从 LRU 端开始,所以把刚刚被访问的数据移到 MRU 端,就可以让它们尽可能地留在缓存中。
- 如果知识兔有一个新数据 15 要被写入缓存,但此时已经没有缓存空间了,也就是链表没有空余位置了,那么,LRU 算法做两件事:
- 数据 15 是刚被访问的,所以它会被放到 MRU 端;
- 算法把 LRU 端的数据 5 从缓存中删除,相应的链表中就没有数据 5 的记录了。
其实,LRU 算法背后的想法非常朴素:它认为刚刚被访问的数据,肯定还会被再次访问,所以就把它放在 MRU 端;长久不访问的数据,肯定就不会再被访问了,所以就让它逐渐后移到 LRU 端,在缓存满时,就优先删除它。
不过,LRU算法在实际实现时,需要用链表管理所有的缓存数据,这会带来额外的空间开销。而且知识兔,当有数据被访问时,需要在链表上把该数据移动到MRU端,如果知识兔有大量数据被访问,就会带来很多链表移动操作,会很耗时,进而降低redis缓存性能。
所以,在redis中,LRU算法被做了简化,以减轻淘汰数据对缓存性能的影响。
- 具体来说,redis会默认记录每一个数据的最近一次访问的时间戳(由键值对数据结构RedisObject 中的 lru 字段记录)。
- 然后知识兔,redis在决定淘汰的数据时,第一次会随机选出N个数据,把它们作为一个候选集合。
- 接下来,redis会比较这N个数据的lru字段,把lru字段值最小的数据从缓存中淘汰出去。
Redis 分享了一个配置参数 maxmemory-samples,这个参数就是 Redis 选出的数据个数N。
- 例如,我们执行如下命令,知识兔可以让 Redis 选出 100 个数据作为候选数据集:
CONFIG SET maxmemory-samples 100
- 当再次淘汰数据时,redis需要挑选数据进入第一次淘汰时创建的候选集合。这里的挑选标准是:能进入候选集合的数据的lru字段值小于候选集合中最小的 lru 值。
- 当有新数据进入候选集合后,如果知识兔候选数据集合中的数据个数达到了maxmemory-samples,redis就把候选集合集中lru子弹值最下的数据淘汰出去。
这样一来,Redis 缓存不用为所有的数据维护一个大链表,也不用在每次数据访问时都移动链表项,提升了缓存的性能。
一旦被淘汰的数据被选定后,Redis 怎么处理这些数据呢?
如何处理被淘汰的数据?
一般来说,一旦被淘汰的数据选定后,如果知识兔这个数据时干净数据,那我们就直接删除;如果知识兔这个数据是脏数据,我们需要把它写回数据库
那怎么判断一个数据到底是干净的还是脏的呢?
- 干净数据和脏数据的区别就在于,和最初从后端数据库里读取时的值相比,有没有被修改过。干净数据一直没有被修改,所以后端数据库里的数据也是最新值。在替换时,它可以被直接删除。
- 而脏数据就是曾经被修改过的,已经和后端数据库中保存的数据不一致了。此时,如果知识兔不把脏数据写回到数据库中,这个数据的最新值就丢失了,就会影响应用的正常使用。
不过,对于redis来说,它决定了被淘汰的数据后,会把它们删除。即使知识兔淘汰的数据时脏数据,redis也不会把它们写回数据库。所以,我们在使用redis缓存时,如果知识兔数据被修改了,需要在数据修改时就将它写回数据库。否则,这个脏数据被淘汰时,会被redis删除,而数据库里也没有最新的数据了。
小结
- Redis 4.0 版本以后一共分享了 8 种数据淘汰策略,从淘汰数据的候选集范围来看,我们有两种候选范围:一种是所有数据都是候选集,一种是设置了过期时间的数据是候选集。另外,无论是面向哪种候选数据集进行淘汰数据选择,我们都有三种策略,分别是随机选择,知识兔根据 LRU 算法选择,以及根据 LFU 算法选择。当然,当面向设置了过期时间的数据集选择淘汰数据时,我们还可以根据数据离过期时间的远近来决定。
- 一般来说,缓存系统对于选定的被淘汰数据,会根据其是干净数据还是脏数据,知识兔选择直接删除还是写回数据库。但是,在 Redis 中,被淘汰数据无论干净与否都会被删除,所以,这是我们在使用 Redis 缓存时要特别注意的:当数据修改成为脏数据时,需要在数据库中也把数据修改过来
- 选择哪种缓存策略是值得我们多加琢磨的,它在筛选数据方面是否能筛选出可能被再次访问的数据,直接决定了缓存效率的高与低。
- 很简单的一个对比,如果知识兔我们使用随机策略,刚筛选出来的要被删除的数据可能正好又被访问了,此时应用就只能花费几毫秒从数据库中读取数据了。而如果知识兔使用 LRU 策略,被筛选出来的数据往往是经过时间验证了,如果知识兔在一段时间内一直没有访问,本身被再次访问的概率也很低了。
- 所以,知识兔建议,先根据是否有始终会被频繁访问的数据(例如置顶消息),来选择淘汰数据的候选集,也就是决定是针对所有数据进行淘汰,还是针对设置了过期时间的数据进行淘汰。候选数据集范围选定后,知识兔建议优先使用 LRU 算法,也就是,allkeys-lru 或volatile-lru 策略。
- 当然,设置缓存容量的大小也很重要,我的建议是:结合实际应用的数据总量、热数据的体量,以及成本预算,把缓存空间大小设置在总数据量的 15% 到 30% 这个区间就可以
下载仅供下载体验和测试学习,不得商用和正当使用。
[ppwp passwords=”zhishitu.cn”]
下载体验
应版权要求,禁止分享,敬请谅解,有问题务必找客服哈。
有问题找客服哈,并领取学习福利!
[/ppwp]