赞
踩
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
本章主要内容:
当Redis作为缓存时,通常在添加数据时自动淘汰旧数据,这是目前流行的内存缓存系统的默认行为。本章主要介绍Redis中一些内存相关的配置以及LRU和LFU淘汰算法
maxmemory配置项用于Redis数据集设置可使用的最大内存量,用户可使用redis.conf文件来设置这个配置项或者使用config set命令来直接设置。
例如为了配置100mb的内存使用量,可以在redis.conf文件内部使用以下命令:
//直接修改redis.conf文件
maxmemory 100mb
//直接连接redis执行如下命令
config set maxmemory 100mb
//通过命令查看当前配置的最大内存量
config get maxmemory
如果把内存设置为0,则表示没有内存使用量的限制,这是64位系统默认的设置,而32位的系统默认的内存使用时3GB。当达到内存的使用量限制时,可以选择不同的操作策略:Redis可能只返回有关命令的错位信息,或者淘汰某些旧数据。
当内存使用量超过maxmemory配置的限制时,Redis可以使用以下策略来淘汰数据:
noeviction
:默认策略,当达到内存使用限制且客户端尝试执行可能会使用更多内存的命令时,返回错误。volatile-lru
:删除设置了过期时间且最近很少使用的键(LRU淘汰算法)allkeys-lru
:删除所有最近很少使用的键(LRU淘汰算法)volatile-lfu
:删除设置了过期时间且最不经常使用的键(LFU淘汰算法)allkeys-lfu
:删除所有最不经常使用的键(LFU淘汰算法)volatile-random
:随机淘汰设置了过期时间的键allkeys-random
:随机淘汰所有键volatile-ttl
:根据过期时间淘汰设置了过期时间的键,越早过期越早淘汰LRU(Least Recently Used,最近很少使用)算法时根据数据在一段时间内使用被使用的记录来淘汰数据。该算法的核心思想是如果数据最近被使用,那么将来被使用的概率更高。可以把LRU算法理解为一个链表,会将新数据放在链表头部,在一段时间内,只要数据被使用就移到链表头部,链表满的时候就从尾部移除数据,即链表尾部的数据被淘汰。
Redis中使用的算法类似于LRU算法,比如修改配置文件maxmemory-samples=5,表示在Redis中随机采用5个键,然后从中淘汰最少使用的键,因此采用的数量与Redis库中键的数量越接近,淘汰的规则就越接近LRU算法。官方默认使用5个键,最大不超过10个,越大越消耗CPU的资源。
采用LRU算法,如果一个热点数据在内存在LRU算法约定的时间段内没有被使用,非热点数据在这段时间段内反而被使用了,就可能误把热点数据淘汰了而留下非热点数据,因此在Redis4之后新增了LFU算法来解决这类问题
LFU(least Frequently Used,最近不常使用)算法根据数据使用的次数来淘汰数据,该算法的核心思想是如果数据过去被使用多次,那么将来被使用的频率更高。LFU算法反应了一个键的热度,不会像LRU算法那样偶尔一次被使用就被误认为是热点数据。同样可以把LFU算法理解为一个链表,新数据放在链表尾部,链表中的数据按照被使用的次数降序排列,被使用次数相同的数据按最近使用的时间降序排列,链表满的时候从链表尾部移除数据,这样就避免了LRU算法可能存在的问题。
注意LFU算法数据使用的时间和使用次数(counter)。
counter的衰减和两个配置有关。如果一个键时间没有被使用,counter就会按照衰减因子的值来减少,在衰减因子的值为1的情况下,N分钟没有被访问,就要减N
// redis.conf文件
lfu-log-factor 10 //概率因子
lfu-decay-time 1 //衰减因子
当内存中没占满时,在Redis中过期的键是通过惰性删除和定期删除来优化的。
Redis每10秒进行一次过期扫描。
//redis.conf文件。默认是10秒
hz 10
在RDB持久化模式中,采用全量持久化,所以在持久化的时候会过滤已经过期的键。
在AOF持久化模式中,当出现键过期就会给AOF文件发送删除命令
需要注意的是,在主从架构中,从节点从来不会主动删除过期的数据。为了保证数据一致性,主节点会发送删除命令给从节点来处理过期的数据
我们在使用Redis中可能会发现一个问题:删除数据后,内存占用率依然很高。这是因为删除数据后,Redis释放的空间会由内存分配器管理,并不会立即返回给操作系统,所以操作系统仍然会记录着Redis分配了大量内存。这往往还伴随着一个潜在的风险:Redis释放的内存空间可能并不是连续的,这些不连续的内存空间很可能处于一种闲置状态。这就导致Redis无法使用这些释放的内存空间来保存数据,这种情况不仅会减少Redis可保存的数据量,还会降低Redis对机器内存的使用率
Redis内存碎片的形成可能由两方面引起:一个是操作系统内存分配机制,另一个是Redis的负载特征
可以使用info memory 命令来查看Redis的内存状态
内存状态信息说明如下:
//Redis为了保存数据实际申请的内存空间,单位是字节
used_memory
//用户数据所占用的内存空间,就是缓存数据的大小
used_memory_human
//操作系统实际分配给Redis的物理内存空间,里面就包含了内存碎片
used_memory_rss
//Redis内存使用的峰值
used_memory_peak
//用户缓存数据的峰值大小
used_memory_peak_human
//执行lua脚本所占用的内存空间
used_memory_lua
//内存碎片率
mem_fragmentation_ratio
内存碎片率的计算公式如下:
mem_fragmentation_ratio = used_memory_rss / used_memory
内存碎片率mem_fragmentation_ratio 大于1且小于1.5是比较合理的,造成内存碎片的原因是无法避免的。mem_fragmentation_ratio 大于1.5时,表示内存碎片率超过了50%,这就需要采取一些措施来降低内存碎片率。
在Redis 4之前,我们只能重启Redis服务,但是这有可能出现下面两个问题:
1)如果Redis中的数据没有持久化,那么重启之后数据会丢失
2)即使Redis数据持久化了,也需要通过AOF或RDB进行恢复,恢复时间较长,那么恢复阶段将无法提供服务。
在Redis 4版本之后,Redis自身提供了一种内存碎片自动清理的方法,在规定的时间内进行内存空间的合并。
相关参数如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。