分享

【死磕 Redis】------ 理解 Redis 的内存

本帖最后由 Mirinda 于 2021-7-22 11:03 编辑

问题导读:
1.Redis 的内存主要消耗在什么地方?
2.Redis 的内存主要包括那些?
3.Redis 的内存管理在那些方面?

我们知道 Redis 的所有数据都存储在内存中,内存是我们系统中的一个非常珍贵的资源,不能随意浪费,所以如何合理高效地利用 Redis 内存就变得非常重要了。本文从两个方面来阐述 Redis 的内存机制:
1.知道 Redis 的内存主要消耗在什么地方
2.如何管理内存

查看内存
在文章【死磕 Redis】----- info 命令详解介绍了 info memory 命令可以查看 Redis 内存消耗情况,是我们分析 Redis 内存使用情况的好工具。执行命令后如下:
a1.png



我们重点关注几个指标:

b1.jpg


这里我们需要重点关注
  1. mem_fragmentation_ratio > 1 说明多出来的部分名没有用于数据存储,而是被内存碎片所消耗,相差越大,说明内存碎片率越严重。
  2. mem_fragmentation_ratio < 1 一般出现在Redis内存交换(Swap)到硬盘导致(used_memory > 可用最大内存时,Redis会把旧的和不适用的数据写入到硬盘,这块空间就叫Swap空间),出现这种情况需要格外关注,硬盘速度远远慢于内存,Redis性能就会变得很差,甚至僵死。
  3. 在理想情况下 mem_fragmentation_ratio 只会比 1 稍微大一点点,也就是 used_memory_rss 的值应该只比 used_memory 稍微高一些。
复制代码

内存消耗划分
Redis 的内存主要包括:对象内存 + 缓冲内存 + 自身内存 + 内存碎片。如下

a2.png



对象内存
对象内存是 Redis 内存中占用最大的一块,存储着所有的用户数据。我们知道 Redis 是一个 key-value 的内存数据库,所有的数据都采用 key-value 型数据类型,每次在创建 key-value 键值对对象的时候都要创建两个对象:key 对象和value 对象。其中 key 对象是字符串,value 对象我们知道有五中数据类型-String、Hash、List、Set、Zset,每种数据类型在使用的时候占用的内存不同。

缓冲内存
主要包括:客户端缓冲、AOF 缓冲区、复制积压缓冲区。

客户端缓冲:普通的客户端连接
AOF 缓冲区:Redis 持久化分为两种:RDB 和 AOF,其中 RDB 是内存快照,AOF 是将 Redis 的命令 append 在文件中,不过在写入文件之前会先写入到缓冲区,然后根据不同的持久化策略向磁盘进行同步。在进行 AOF 重写时也有一个AOF 重写缓冲区。一般 AOF 缓冲区都会比较小。
复制积压缓冲区:主要用于主从同步。在进行主从同步时,Redis 会将最新的命令写入到复制积压缓冲区,在进行复制的时候,会校验复制偏移量是否在复制积压缓冲区中,如果是则进行部分复制,否则进行全量复制。它默认情况下是 1MB,我们需要根据实际请求适当调整他的大小,毕竟设置太小的话,可能会使部分复制退化为全量复制。

自身内存

自身内存主要指 AOF/RDB 的时候 Redis 创建子进程内存的消耗,一般这部分的消耗会比较小。

内存碎片
目前可选的分配器有 jemalloc、glibc、tcmalloc,默认 jemalloc。

出现高内存碎片问题的情况:大量的更新操作,比如 append、setrange;大量的过期键删除,释放的空间无法得到有效利用。

解决办法:数据对齐,安全重启(高可用/主从切换)。


内存管理
设置 maxmemory
如果我们不设置 maxmemory ,Redis 则默认使用无限内存,所以为了 Redis 不系统的内存耗尽,我们在使用 Redis 的时候尽量去配置 maxmemory,给 Redis 设置内存使用上限。maxmemory 配置的是 Redis 的实际使用内存,即 used_memory,但是由于有内存碎片的存在,所以 Redis 实际使用的内存会比 used_memory 要大,在合理情况下一般只会大一点点。

配置内存回收策略
Redis 回收内存大致有两种机制:
删除达到过期时间的对象
当内存达到 maxmemory 时触发内存溢出控制策略,强制删除选择出来的对象
Redis 删除过期键值对对象一般有两种策略:惰性删除和主动定时任务删除。

惰性删除:这种删除策略,Redis 不会主动去删除已经过期的键值对,而是等待客户端去读取带有超时属性的键时,如果已经超时了则删除该键值对对象,然后返回空。这样有一个好处就是节省了 CPU ,因为 Redis 不需要单独去维护 TTL 链表来处理过期键的删除,但是有一个坏处就是如果过期的键一直都没有被访问,则永远不会被删除了。那么怎么解决呢?Redis 提供了一个定时任务的删除机制来补救。

定时任务删除:Redis 内部维护一个定时任务,默认是每秒运行 10 次,删除逻辑如下图:

a3.png


内存溢出控制策略
当 Redis 所用内存达到 maxmemory 上限时会触发相应的溢出控制策略。Redis支持6种策略,如下所示:

b2.jpg


当 Redis 因为内存溢出删除键时,可以通过执行 info stats 命令查看 evicted_keys 指标找出当前 Redis 服务器已剔除的键数量。

参考
《Redis 开发与运维》
理解Redis的内存


最新经典文章,欢迎关注公众号









没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条