当前位置: 首页 > 后端技术 > Java

Redis的内存回收真的很牛逼!!!

时间:2023-04-01 18:54:35 Java

1。过期键处理Redis之所以性能强大,主要是基于内存存储。但是单节点Redis的内存大小不宜过大,会影响持久化或者主从同步的性能。我们可以通过修改配置文件来设置Redis的最大内存:maxmemory1gb当内存使用量达到上限时,就不能再存储数据了。为了解决这个问题,Redis提供了一些实现内存回收的策略:首先要了解的是:redis是一个存储key-value的数据库系统,那么它的源码中是如何存储所有key-value对的呢?Redis本身就是一个典型的key-value内存存储数据库,所以所有的key和value都存储在前面学过的Dict结构中。但是在它的数据库结构中,有两种Dicts:一种是用来记录key-value的;另一个用于记录key-TTL。内部结构dict是一个哈希结构,用来存储所有的键值对。expires也是一个hash结构,用来存储所有设置过期时间的key-value对,但它的值是过期时间。这里有两个问题需要我们思考:Redis如何知道一个key是否过期?使用两个Dict分别记录key-value对和key-ttl对。TTL过期是不是马上删除?总结:Redis的过期删除策略是:延迟删除和定时删除结合使用延迟删除。惰性删除:顾名思义不会在TTL过期后立即删除,而是在访问某个key时检查key。生存时间,如果已经过期,将被删除。Periodicdeletion周期性删除:顾名思义使用定时任务,周期性地采样一些过期的key,然后删除。执行周期有两种:Redis服务初始化函数initServer()设置定时任务,根据server.hz的频率进行过期key清理。beforeSleep()函数在SLOWRedis的每个事件周期之前被调用,进行过期key的清理,模式为FASTSLOW模式规则:执行频率受server.hz影响,默认为10,即每秒执行10次,每次执行周期为100ms。执行清理不超过一个执行周期的25%。默认的慢速模式,不超过25ms,一次遍历db,一次遍历db中的bucket,提取20个key判断是否过期。如果未达到时限(25ms)且key过期比例大于10%,则重新采样,否则,结束FAST模式规则(过期key比例小于10%不执行):执行频率受beforeSleep()调用频率的影响,但是两次FAST模式之间的间隔不能小于2ms执行清理时间不超过1ms逐条遍历db,遍历db中的buckets一个一个抽取20个key判断是否过期如果没有达到时限(1ms)且过期key比例大于10%,则重新采样,否则结束2内存淘汰策略①,设置最大内存Redis的  在配置文件redis.conf中,最大内存可以通过参数maxmemory来设置:如果不设置这个参数,默认是无限制的,但是通常设置为物理内存的四个字节3/2。设置内存消除方式。当现有内存大于maxmemory时,会触发redis主动淘汰内存的方法。通过设置maxmemory-policy,有以下几种淘汰方式:volatile-lru:设置有过期时间的key使用LRU算法淘汰;allkeys-lru:使用LRU算法淘汰所有key;volatile-lfu:使用LFU算法淘汰设置了过期时间的键;allkeys-lfu:使用LFU算法淘汰所有key;volatile-random:设置了过期时间的key使用随机淘汰;allkeys-random:所有keys使用随机淘汰;volatile-ttl:设置过期时间的key根据过期时间进行淘汰,越早过期越早淘汰;noeviction:默认策略,当内存达到set的最大值时,所有申请内存的操作都会报错(如set,lpush等),而只读操作如get命令可以正常执行;比较容易混淆的有两个:LRU(LeastRecentlyUsed),最近最少使用。从当前时间减去上次访问时间。值越大,淘汰优先级越高。LFU(LeastFrequentlyUsed),使用频率最低。会统计每个key的访问频率,值越小淘汰优先级越高。*LRU、LFU、volatile-ttl都是近似随机算法;使用以下参数maxmemory-policy配置淘汰策略:#配置文件maxmemory-policynoeviction#命令行127.0.0.1:6379>configgetmaxmemory-policy1)"maxmemory-policy"2)"noeviction"127.0.0.1:6379>configsetmaxmemory-policyallkeys-randomOK127.0.0.1:6379>configgetmaxmemory-policy1)"maxmemory-policy"2)"allkeys-random"Redis数据会被封装成一个RedisObject结构:LFU的访问次数之所以称为逻辑访问次数,是因为不是每次访问key都统计一次,而是通过计算一个0到1之间的随机数R(oldtimes*lfu_log_factor+1)来计算,记为P。如果R