当前位置:   article > 正文

Redis内存相关策略和内存碎片_maxmemory

maxmemory

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本章主要内容:

  • 数据逐出策略
  • LRU算法
  • LFU算法
  • Redis内存碎片管理

当Redis作为缓存时,通常在添加数据时自动淘汰旧数据,这是目前流行的内存缓存系统的默认行为。本章主要介绍Redis中一些内存相关的配置以及LRU和LFU淘汰算法


1 maxmemory配置

maxmemory配置项用于Redis数据集设置可使用的最大内存量,用户可使用redis.conf文件来设置这个配置项或者使用config set命令来直接设置。

例如为了配置100mb的内存使用量,可以在redis.conf文件内部使用以下命令:

//直接修改redis.conf文件
maxmemory 100mb
//直接连接redis执行如下命令
config set maxmemory 100mb
//通过命令查看当前配置的最大内存量
config get maxmemory
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

如果把内存设置为0,则表示没有内存使用量的限制,这是64位系统默认的设置,而32位的系统默认的内存使用时3GB。当达到内存的使用量限制时,可以选择不同的操作策略:Redis可能只返回有关命令的错位信息,或者淘汰某些旧数据。

2 数据淘汰策略

当内存使用量超过maxmemory配置的限制时,Redis可以使用以下策略来淘汰数据:

  • noeviction:默认策略,当达到内存使用限制且客户端尝试执行可能会使用更多内存的命令时,返回错误。
  • volatile-lru:删除设置了过期时间且最近很少使用的键(LRU淘汰算法)
  • allkeys-lru:删除所有最近很少使用的键(LRU淘汰算法)
  • volatile-lfu:删除设置了过期时间且最不经常使用的键(LFU淘汰算法)
  • allkeys-lfu:删除所有最不经常使用的键(LFU淘汰算法)
  • volatile-random:随机淘汰设置了过期时间的键
  • allkeys-random:随机淘汰所有键
  • volatile-ttl:根据过期时间淘汰设置了过期时间的键,越早过期越早淘汰

3 LRU 算法

LRU(Least Recently Used,最近很少使用)算法时根据数据在一段时间内使用被使用的记录来淘汰数据。该算法的核心思想是如果数据最近被使用,那么将来被使用的概率更高。可以把LRU算法理解为一个链表,会将新数据放在链表头部,在一段时间内,只要数据被使用就移到链表头部,链表满的时候就从尾部移除数据,即链表尾部的数据被淘汰。

Redis中使用的算法类似于LRU算法,比如修改配置文件maxmemory-samples=5,表示在Redis中随机采用5个键,然后从中淘汰最少使用的键,因此采用的数量与Redis库中键的数量越接近,淘汰的规则就越接近LRU算法。官方默认使用5个键,最大不超过10个,越大越消耗CPU的资源。

采用LRU算法,如果一个热点数据在内存在LRU算法约定的时间段内没有被使用,非热点数据在这段时间段内反而被使用了,就可能误把热点数据淘汰了而留下非热点数据,因此在Redis4之后新增了LFU算法来解决这类问题

4 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 //衰减因子
  • 1
  • 2
  • 3
  • 4

5 数据过期删除策略

当内存中没占满时,在Redis中过期的键是通过惰性删除和定期删除来优化的。

  • 惰性删除:当键被访问时,检查该键的过期时间,如果过期就删除此键。未过期但是没有被访问的键仍然存放在内存中,自然就占用的内存资源
  • 定期删除:每隔一段时间,随机检查设置了过期时间的键并删除已过期的键。

Redis每10秒进行一次过期扫描。

  • 第一步,随机取20个设置了过期策略的键。
  • 第二步,检查这20个键,删除其中已过期的键。
  • 第三步,如果有超过25%的键已过期则重复第一步。
//redis.conf文件。默认是10秒
hz 10
  • 1
  • 2

6 主从架构和数据持久化对数据过期的处理

  • 在RDB持久化模式中,采用全量持久化,所以在持久化的时候会过滤已经过期的键。

  • 在AOF持久化模式中,当出现键过期就会给AOF文件发送删除命令

  • 需要注意的是,在主从架构中,从节点从来不会主动删除过期的数据。为了保证数据一致性,主节点会发送删除命令给从节点来处理过期的数据

7 内存碎片

我们在使用Redis中可能会发现一个问题:删除数据后,内存占用率依然很高。这是因为删除数据后,Redis释放的空间会由内存分配器管理,并不会立即返回给操作系统,所以操作系统仍然会记录着Redis分配了大量内存。这往往还伴随着一个潜在的风险:Redis释放的内存空间可能并不是连续的,这些不连续的内存空间很可能处于一种闲置状态。这就导致Redis无法使用这些释放的内存空间来保存数据,这种情况不仅会减少Redis可保存的数据量,还会降低Redis对机器内存的使用率

7.1 Redis内存碎片的形成

Redis内存碎片的形成可能由两方面引起:一个是操作系统内存分配机制,另一个是Redis的负载特征

  • 内存分配机制:内存分配器的分配策略决定了操作系统无法做到按需分配。这是因为内存分配器一般是按照固定大小来分配内存的,而不是按照应用程序申请的内存空间大小来给程序分配内存的。Redis可以使用libc、jemalloc、tcmalloc多种内存分配器来分配内存,默认使用jemalloc。jemalloc的分配策略之一就是按照固定大小划分内存空间,比如8字节、16字节、32字节、48字节等等。当程序申请的内存大小最接近某个固定值时,jemalloc会分配给它相应大小的空间。如果Redis每次向分配器申请的内存大小不一样,那么这种方式就会形成内存碎片。
  • Redis的负载特征:在业务中,我们会对键值对进行修改或删除操作,产生对内存空间的申请和释放操作。如果修改后的键值对变大或者变小了,就需要占用额外的内存空间或释放不用的内存空间,或者删除的键值对不再需要内存空间了,此时会把内存空间释放出来,形成空闲的内存空间。

7.2 内存使用情况

可以使用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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在这里插入图片描述

内存碎片率的计算公式如下:

mem_fragmentation_ratio = used_memory_rss / used_memory

内存碎片率mem_fragmentation_ratio 大于1且小于1.5是比较合理的,造成内存碎片的原因是无法避免的。mem_fragmentation_ratio 大于1.5时,表示内存碎片率超过了50%,这就需要采取一些措施来降低内存碎片率。

7.3 清理内存碎片

在Redis 4之前,我们只能重启Redis服务,但是这有可能出现下面两个问题:

1)如果Redis中的数据没有持久化,那么重启之后数据会丢失
2)即使Redis数据持久化了,也需要通过AOF或RDB进行恢复,恢复时间较长,那么恢复阶段将无法提供服务。

在Redis 4版本之后,Redis自身提供了一种内存碎片自动清理的方法,在规定的时间内进行内存空间的合并。

相关参数如下:

  • activedefrag no:是否启用碎片整理 ,默认是no
  • active-defrag-ignore-bytes 100mb:内存碎片的字节数达到100MB时开始清理碎片
  • active-defrag-threshold-lower 10:内存碎片空间占操作系统分配给Redis的总内存空间的比率达到10%时开始清理碎片
  • active-defrag-cycle-min 1:自动清理过程所用CPU的时间比例不低于1%,以保证能正常清理
  • active-defrag-cycle-max 25:自动清理过程所用CPU时间的比例不高于25%,一旦超过就停止清理,从而在清理内存时大量的内存复制阻塞了Redis,导致Redis服务响应缓慢。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/木道寻08/article/detail/755834
推荐阅读
相关标签
  

闽ICP备14008679号