redis淘汰策略有哪些,Redis过期删除策略和内存淘汰策略
redis淘汰策略有哪些,Redis过期删除策略和内存淘汰策略详细介绍
本文目录一览: redis淘汰策略有哪些
具体如下。volatile-lru:从已设置过期时间的哈希表(server.db[i].expires)中随机挑选多个key,然后在选到的key中用lallkey-lru:从所有key的哈希表(server.db[i].dict)中随机挑选多个key,然后再选到的key中利用lru算法淘汰volatile-ttl:从已设置过期时间的哈希表(server.db[i].expires)中随机挑选多个key,然后在选到的key中选择.volatile-random:从已设置过期时间的哈希表(server.db[i].expires)中随机挑选key淘汰掉allkey-random:从所有的key的哈希表server.db[i].dict)中随机挑数据淘汰。Redis是一个开源的使用ANSIC语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
Redis过期后,是用什么淘汰策略?
Redis 中数据过期策略采用定期删除+惰性删除策略。
定期删除策略:Redis 启用一个定时器定时监视所有的 key,判断key是否过期,过期的话就删除。这种策略可以保证过期的 key 最终都会被删除,但是也存在严重的缺点:每次都遍历内存中所有的数据,非常消耗 CPU 资源,并且当 key 已过期,但是定时器还处于未唤起状态,这段时间内 key 仍然可以用。
惰性删除策略:在获取 key 时,先判断 key 是否过期,如果过期则删除。这种方式存在一个缺点:如果这个 key 一直未被使用,那么它一直在内存中,其实它已经过期了,会浪费大量的空间。
2、定期删除+惰性删除策略是如何工作的?
这两种策略天然的互补,结合起来之后,定时删除策略就发生了一些改变,不在是每次扫描全部的 key 了,而是随机抽取一部分 key 进行检查,这样就降低了对 CPU 资源的损耗,惰性删除策略互补了为检查到的key,基本上满足了所有要求。但是有时候就是那么的巧,既没有被定时器抽取到,又没有被使用,这些数据又如何从内存中消失?没关系,还有内存淘汰机制,当内存不够用时,内存淘汰机制就会上场。Redis 内存淘汰机制有以下几种策略:
noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。(Redis 默认策略)
allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 Key。(推荐使用)
allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 Key。
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 Key。这种情况一般是把 Redis 既当缓存,又做持久化存储的时候才用。
volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 Key。
volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 Key 优先移除。
修改内存淘汰机制只需要在 redis.conf 配置文件中配置 maxmemory-policy 参数即可。
Redis过期删除策略和内存淘汰策略
Redis可以用使用 expire 指令设置过期时间,在Redis内部,每当我们设置一个键的过期时间时,Redis就会将该键带上过期时间存放到一个过期字典中。当我们查询一个键时,Redis便首先检查该键是否存在过期字典中,如果存在,那就获取其过期时间。然后将过期时间和当前系统时间进行比对,比系统时间大,那就没有过期;反之判定该键过期。
那对于过期数据,一般有三种方式进行处理:
Redis的过期删除策略: 惰性删除 和 定期删除 两种策略配合使用。
spring-boot-starter-data-redis 包中提供了监听过期的类,对于key过期,需要得到通知,做业务处理的,可以做此监听。
springboot整合Redis参考, SpringBoot整合Redis - (jianshu.com) 在整合Redis的基础上,在新加监听配置
监听配置类
监听类
将Redis用作缓存时,如果内存空间用满,就会自动驱逐老的数据。
Redis中有6种淘汰策略:
redis.conf 文件中配置策略,有2个地方:
Redis内存配置和淘汰策略
1.在redis安装目录下找到redis.conf,打开找到如下行:
其中的maxmemory
即为最大内存配置项,默认是注释掉的会采用 默认的最大内存大小 :在64位操作系统下不限制内存大小,在32位操作系统下最多使用3GB。
2.在客户端通过命令行查看
这里结果为0表示未手动指定过最大内存,采用默认的最大内存。
一般推荐Redis设置内存为最大物理内存的四分之三。
1.在配置文件redis.conf中指定maxmemory参数,例如,如果最大内存是200M,则在配置文件中添加 maxmemory 209751200 ; 2.通过命令 config set maxmemory 209751200 设置,注意,这里如果是通过命令行设置的最大内存大小,在配置文件redis.conf中并不会添加 maxmemory 209751200 这一行内容。
当Redis达到最大的可用内存时,再向其中存入数据则会报OOM,因此,要避免无限制存入数据导致OOM,则需要采用合适的内存淘汰策略。
在讨论Redis的内存淘汰策略之前,我们要先对Redis中过期键的删除机制有个大体的了解;实际上,过期键的删除策略有三种,每种策略下过期键的删除时机均不同。 1. 定时删除 所谓定时删除,就是在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即删除对键的删除操作。其能够对过期键进行立即删除,对内存是友好的,但是因为要维护定时器,对cpu是不友好的。 2. 惰性删除 所谓惰性删除,就是放任过期键不管,但每次获取键时,都检查取得的键是否过期,如果过期的话,就删除该键。如果没有过期,就返回该键。惰性删除对cpu友好,但是由于其无法主动删除过期键,当过期键大量积聚时会占用很大内存,对内存不友好。 3. 定期删除 所谓定期删除,是前两种删除策略的一种折中。会每隔一段时间执行一次删除过期键操作,并通过限制操作执行的时长和频率来减少删除操作对cpu时间的影响。 定期删除会周期性轮询redis库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度,其特点为: a)CPU占用设置有峰值,检测频度可自定义设置。 b)内存压力有限,长期占用内存的冷数据会被持续清理。 总结下来,定期删除会周期性抽查存储空间(随机抽查、重点抽查)。 定期删除的难点在于如何确定产出操作执行的时长和频率,如果删除操作执行的太过频繁,或者执行的时间太长,定期删除策略就会退化成定时删除策略,以至于将CPU时间过多的消耗在删除键上面。如果删除操作执行的太少,或者执行的时间太短,定期删除策略又会和惰性删除策略一样,出现内存浪费的情况。因此,必须合理的设置定期删除策略的执行时长和执行频率。 定期删除在一定程度上是一种合理有效的过期键删除策略,但是由于其在执行时长和执行频度的局限性,必须要有另一种机制(策略)确保内存能够获得回收,因此,就需要引入内存淘汰策略。
在redis.conf中指出内存淘汰策略有有以下八种: 1. volatile-lru :从已设置过期时间的key中挑选最近最少使用的数据淘汰; 2. allkeys-lru :从全部key中挑选最近最少使用的数据淘汰; 3. volatile-lfu :从已设置过期时间的key中挑选使用频率最低的数据淘汰; 4. allkeys-lfu :从全部key中挑选使用频率最低的数据淘汰; 5. volatile-random :从已设置过期时间的key中任意选择数据淘汰; 6. allkeys-random :从全部key中任意选择数据淘汰 7. volatile-ttl :从已设置过期时间的key中挑选将要过期的数据淘汰; 8. no-enviction :禁止驱逐数据,这也是默认策略。当内存不足以容纳新入数据时,新写入操作就会报错。
内存淘汰策略的设置与查看
Redis过期键删除策略和内存淘汰策略
????惰性删除+定期删除
????键过期后并不会立即删除,而是等到使用它时,先判断该键是否已经过期,如果过期则删除
????对内存不友好,对CPU友好
????redis每隔一段时间随机检测一部分数据(并不是全部)是否过期,如果已过期则删除
????redis.conf中的hz参数用来配置每秒执行几次定期删除,默认值是10,即100ms/次
????redis.conf中的maxmemory-samples参数用来指定每次检测几条数据,默认5
????对CPU不友好,对内存友好
????redis.conf中的maxmemory参数配置了redis的最大内存,maxmemory-policy配置了内存淘汰策略,当redis内存达到最大后,会根据内存淘汰策略淘汰部分数据。
????redis提供了8种内存淘汰策略:
????????no-eviction:当内存达到最大后,新数据不能写入,会报错
????????allkeys-lru:当内存达到最大后,淘汰最近最少使用的数据(最常用的策略)
????????allkeys-random:当内存达到最大后,随机淘汰
????????allkeys-lfu:当内存达到最大后,淘汰最少使用的数据
????????volatitle-lru:当内存达到最大后,从设置了过期键的数据中,淘汰最近最少使用的数据
????????volatitle-random:当内存达到最大后,从设置了过期键的数据中,随机淘汰
????????volatitle-lfu:当内存达到最大后,从设置了过期键的数据中,淘汰最少使用的数据
????????volatitle-ttl:当内存达到最大后,淘汰最早过期的数据
????标准的LRU算法需要维护一个链表,当某个数据被使用时就把它放到链表头部,这样就保证了链表是按照使用时间排序的,当需要淘汰数据时,就从链表尾部删除部分数据。
????标准LRU算法要进行大量的计算,redis采取了近似LRU算法的操作。
????redis给每个键维护了一个24bit的属性字段,用来记录最后一次使用的时间戳。redis根据maxmemory-samples随机抽取一部分数据,将最旧的数据淘汰,指到内存降下来。后来redis又引入了淘汰池,淘汰池内的数据量等于maxmemory-samples,每次淘汰时将随机抽取的数据和淘汰池中的数据合并,淘汰最旧的数据,然后将剩余最旧的数据维护到淘汰池中,等待下次循环。
? ? 为什么需要LFU算法?
? ? 现在假设这种场景:redis中有两个键A和B,其使用频率如上面所示,当到达$时,因为A的使用时间比B晚,按照LRU算法会淘汰B,但是从使用频率上看,B明显比A使用的更频发,应该淘汰A。
? ? 为了解决上面的问题,Redis引入了LFU算法,淘汰最少使用的数据。原理如下:
? ? LFU给每个数据维护了一个计数器,每次使用都会使计数器增加,淘汰使用次数最少的键。但是这样又有新的问题:
? ? ①新的key如果计数器为0,可能就会一直被淘汰
? ? ? ? ? ? redis解决方案:redis给每个新的键的计数器一个初始值
? ? ②某个键可能前一段时间被频繁使用,但是一段时间后使用频率就会下降。
? ??????????redis解决方案:如果某个键一段时间不使用,计数器会减小
??
Redis缓存淘汰策略
LRU (less recently used)是Redis唯一支持的回收算法,当缓存占用的内存空间达到设置的最大空间时,会自动驱逐老的数据。
一般来说:
volatile-lru 和 volatile-random 主要应用场景是:既有缓存,又有持久key的实例中,一般这类场景应该使用单独的Redis实例。
值得一提的是,设置expire会消耗额外的内存,所以 使用allkey-lru可以更高效地使用内存 ,因为这样使用的时候不需要设置过期时间。
Redis使用的并不是完全LRU算法,而是近似LRU算法。被删除的key也不一定是最满足LRU特征的key,而是通过近似LRU算法抽样,然后删除访问时间最古老的key。这样做得原因也是为了节省内存空间,在新版本3.0开始,使用pool(池子)来作为候选,这大大提高了算法效率,也使得近似LRU算法越来越接近纯LRU算法。
Redis数据的过期与淘汰
懒惰处理 Redis在get操作时遇到过期的key会进行删除操作。
集中处理 Redis会将设置了过期时间的key放到一个独立的字典里,默认每秒10次过期扫描。扫描方式:
为防止扫描时间过长,扫描时间限制为25ms,开发时应尽量避免大量key同时过期。 从库不会进行过期扫描,主库删除时,会在AOF文件里增加一条del指令,同步到所有从库,从库通过此指令来删除。由于指令的同步存在异步,所以会出现主从数据不一致的情况。
当Redis内存超出物理内存限制时,内存数据会开始和磁盘产生频繁的交换,使得性能急剧下降。为了限制内存的使用,Redis提供参数 maxmemory 来限制最大内存,当内存超出后,会有以下策略( maxmemory-policy )来淘汰key以腾出空间:
由于LRU算法需要消耗大量的额外内存,redis采用一种近似的LRU算法。它给每个 key 增加了一个额外的小字段(24bit),也就是最后一次被访问的时间戳。每次执行写操作时,如果发现内存超出 maxmemory ,就随机采样5个(参数 maxmemory_samples 配置)key,然后淘汰最旧的。如果淘汰之后还是超出,那就继续随机淘汰,直到不超出为止。如果 maxmemory-policy 是volatile-xxx,就从设置过期时间的key里采样,否则就从所有key里采样。 Redis3.0里增加了一个淘汰池,就是一个大小为 maxmemory_samples 的数组。每次淘汰时会将随机出来的key和数组里的key融合,淘汰掉最旧的一个,然后将剩下的较旧的key放到淘汰池里给下个循环用。
redis的删除del在删除一个大对象的时候有可能造成卡顿。为了解决这个问题Redis4.0引入了unlink指令,将这个key的对象引用从Redis内存数据里删除,将删除操作封装成一个任务丢到一个异步队列里。然后有个异步线程会从这个队列里取出任务并执行。 清空操作 flushdb 和 flushall ,在Redis4.0后,在指令后面增加 async ,就也可以像上面一样异步执行。
《Redis深度历险:核心原理和应用实践》
Redis 配置过期自动删除策略
Redis操作是基于内存的,大小有限。当内存不足或占用过高时,需要自动放弃一些未到期的数据
Redis 默认 的生效的配置为 noeviction ,需要根据不同的业务选择不同的淘汰策略
volatile-lru:在设置过期时间的数据集合里淘汰最近访问最少的数据
allkeys-lru:所有数据集合中淘汰最近访问最少的数据
volatile-lfu:在设置过期时间的数据集合里淘汰访问频率最低的数据
allkeys-lfu:所有数据集合中淘汰访问频率最低的数据
volatile-random:在设置过期时间的数据集合里,随机淘汰
allkeys-random:在所有的数据集合随机淘汰
volatile-ttl:在设置过期时间的数据集合里,淘汰剩余存活时间 (TTL) 最少的数据
noevictionl:当内存不足以写入新数据时,拒绝新数据写入。Redis 默认策略
我这里越久的数据价值越低,不在乎调用次数。所以选择
volatile-ttl
找到配置 maxmemory-policy 默认被注释 生效策略 noevictionl
保存
重启redis 生效
MySQL里有2000w数据,redis中只存20w数据,如何保证redis中数据都是热点数据
计算20w的热点数据占据内存的大小。然后在Redis中,配置最大内存容量,在redis.conf文件maxmemory
标签中配置。当redis内存数据大小上升到一定大小的时候,就会施行数据淘汰策略。Redis中提供了6中数据淘汰策略:1.volatitle-lru 从设置了过期时间的数据集中,选择最近最少使用的数据删除2.volatitle-ttl 从设置了过期时间的数据集中,选择将要过期的数据删除3.volatitle-random 从设置了过期时间的数据中,随机选择数据进行删除4.Allkeys-lru 从数据集中挑选最近最少使用的数据删除5.Allkeys-random 从数据集中随机挑选数据进行淘汰6.no-enviction(驱逐):禁止淘汰数据因为我们的应用保存热点数据,也就是对缓存的访问符合幂律分布,所以应该选择Allkeys-lru淘汰策略。存放热点数据,不能为数据设置过期时间,设置过期时间也会占用内存。MySQL里有2000w数据,redis中只存20w数据,如何保证redis中数据都是热点数据标签:如何mysqlsqlkeymemorylru保存选择env