删除策略(回收策略):是当数据到期,redis对过期数据的处理策略。
比如验证码、token等。当数据过了期限后,应该要被删除。
合集参考:面试宝典
Redis中提供了三种删除策略:
1、定时删除当放入数据后,设置一个定时器,当定时器读秒完毕后,将对应的数据从dict中删除。
优点: 内存友好,数据一旦过期就会被删除 缺点: CPU不友好,定时器耗费CPU资源,尤其是当CPU还在尽力处理其他事情的时候,这时候如果有key过期,就可能两边(redis和其他服务)体验都不好,并且当定时key越多,分配的资源就越多,就越影响性能
用时间换空间
2、惰性删除当数据过期的时候,不做任何操作。当访问数据的时候,查看数据是否过期,如果过期返回null,并且将数据从内存中清除。如果没过期,就直接返回数据。
优点: CPU友好,数据等到过期并且被访问的时候,才会删除。 缺点: 内存不友好,会占用大量内存,有较大的OOM风险
用空间换时间
3、定期删除定期删除是定时删除和惰性删除的折中方案。 每隔一段时间对redisServer中的所有redisDb的expires依次进行随机抽取检查。 具体来说,就是周期性轮询redis库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度。 这样做有两个特点:
cpu性能占用设置有峰值,检测频度可自定义设置。 内存压力不是很大,长期占用内存的冷数据会被持续清理。
原理
(1)redis中有一个server.hz定义了每秒钟执行定期删除的次数,每次执行的时间为250ms/server.hz。
(2)redis中会维护一个current_db变量来标志当前检查的数据库。current_db++,当超过数据库的数量的时候,会重新从0开始。
(3)定期检查就是执行一个循环,循环中的每轮操作会从current_db对应的数据库中随机依次取出w个key,查看其是否过期。如果过期就将其删除, 并且记录删除的key的个数。如果过期的key个数大于w25%,就会继续检查当前数据库,当过期的key小于w25%,会继续检查下一个数据库。
(4)当执行时间超过规定的最大执行时间的时候,会退出检查。
(5)一次检查中可以检查多个数据库,但是最多检查数量是redisServer中的数据库个数,也就是最多只能从当前位置检查一圈。
伪代码
time_limit = 250ms/server.hz; //每次检查运行的最大时间 for(int current_db = 0;current_db < dbs_per_call;current_db++){ //dbs_per_call为server中数据库的个数,也就是每次检查最多检查一轮所有的数据库 redisDb = redisServer.db[current_db]; //获取数据库的过期哈希表 expires = redisDb.expires; //获取开始的时间 long start = time(); int expired = 0; int w = 20; do{ int i = 0; while(i++ < w){ long now = time(); //如果随机找的key过期了 if(expire(now,random(expires))){ //过期数量++ expired ++; } } //如果运行时间超过了规定时间,就退出检查,下一次定期检查直接检查下一个数据库 if(time() - start > timelimit){ return; } //如果过期数量超过25%,继续检查当前数据库 }while(expired > w * 25%);
优点: 通过控制定时时间来动态的调整CPU和内存之间的状态,十分灵活。
缺点: 定期删除的定时时间十分重要,如果时间过短,就会对CPU造成很大压力。如果时间过长,就会造成过期数据挤压内存。
难点: 定期删除策略的难点是不确定删除操作执行的时长和频率:
如果删除操作执行的太频繁或者执行的时间太长,定期删除策略就会退化成定时删除策略,以至于将CPU时间过去的消耗在删除过期键上面。
如果删除操作执行的太少或者执行的时间太短,定期删除策略又会和惰性删除策略一样,出现浪费内存的情况。因此,如果采用定期删除策略的话,服务器必须根据情况,合理地设置删除操作的执行时长和执行频率。
淘汰策略:是当数据放不下的时候,淘汰其他数据的策略。
1)noeviction: 不删除,直接返回报错信息。
2)allkeys-lru:移除最久未使用(使用频率最少)使用的key。
3)volatile-lru:在设置了过期时间的key中,移除最久未使用的key。
4)allkeys-random:随机移除某个key。
5)volatile-random:在设置了过期时间的key中,随机移除某个key。
6)volatile-ttl: 在设置了过期时间的key中,移除准备过期的key。
7)allkeys-lfu:移除最近最少使用的key。
8)volatile-lfu:在设置了过期时间的key中,移除最近最少使用的key。
allkeys-xxx:allkeys开头的是对Redis中的所有key都在淘汰范围内。
volatile-xxx:volatile开头的是对Redis中的设置了超时时间的key列入淘汰范围。
如何配置
1.获取和配置Redis能使用的最大内存大小
方式一:修改配置文件中的 maxmemory,放开注释, 根据业务需求设置大小
maxmemory <100mb #设置最大内存大小为100MB
方式二:命令行设置
127.0.0.1:6379> config get maxmemory #命令行查看当前设置最大内存 127.0.0.1:6379> config set maxmemory 100mb #设置Redis最大占用内存大小为100MB
如果不设置最大内存大小或者设置最大内存大小为0,在64位操作系统下不限制内存大小,在32位操作系统下最多使用3GB内存。32 位的机器最大只支持 4GB 的内存,而系统本身就需要一定的内存资源来支持运行,所以 32 位机器限制最大 3 GB 的可用内存。
2.获取和配置redis内存淘汰策略
方式一:修改配置文件中的 maxmemory-policy ,放开注释,根据业务需求修改即可
maxmemory-policy noeviction #noeviction 为默认的策略,根据业务需求修改即可
方式二:命令行设置
127.0.0.1:6379> config get maxmemory-policy #命令行查看当前淘汰策略 127.0.0.1:6379> config set maxmemory-policy noeviction #noeviction 为默认的策略
公众号,感谢关注