内存消耗划分

社区redis输出缓存区有哪几种 redis 缓冲区_sed

自身内存

Redis空进程自身内存消耗非常少,通常used_memory_rss在3MB左右,used_memory在800KB左右,一个空的Redis进程消耗内存可以忽略不计。

对象内存

对象内存存储着用户所有的数据,对象内存消耗可以简单理解为sizeof(keys)+sizeof(values)。

缓冲内存

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

  1. 客户端缓冲指的是所有接入到Redis服务器TCP连接的输入输出缓冲。
  2. 复制积压缓冲区:Redis在2.8版本之后提供了一个可重用的固定大小缓冲区用于实现部分复制功能,根据repl-backlog-size参数控制,默认1MB。对于复制积压缓冲区整个主节点只有一个,所有的从节点共享此缓冲区,因此可以设置较大的缓冲区空间,如100MB,这部分内存投入是有价值的,可以有效避免全量复制
  3. AOF缓冲区:这部分空间用于在Redis重写期间保存最近的写入命令。AOF缓冲区空间消耗用户无法控制,消耗的内存取决于AOF重写时间和写入命令量,这部分空间占用通常很小。
内存碎片

正常的碎片率(mem_fragmentation_ratio)在1.03左右。但是当存储的数据长短差异较大时,以下场景容易出现高内存碎片问题:

  • 频繁做更新操作,例如频繁对已存在的键执行append、setrange等更新操作。
  • 量过期键删除,键对象过期删除后,释放的空间无法得到充分利用,导致碎片率上升。

出现高内存碎片问题时常见的解决方式如下:

  • 数据对齐:在条件允许的情况下尽量做数据对齐,比如数据尽量采用数字类型或者固定长度字符串等,但是这要视具体的业务而定,有些场景无法做到。
  • 安全重启:重启节点可以做到内存碎片重新整理,因此可以利用高可用架构,如Sentinel或Cluster,将碎片率过高的主节点转换为从节点,进行安全重启。
子进程内存消耗

子进程内存消耗主要指执行AOF/RDB重写时Redis创建的子进程内存消耗。

内存管理
设置内存上限

使用maxmemory参数限制最大可用内存(Redis实际使用的内存量,也就是used_memory统计项对应的内存)

  • 用于缓存场景,当超出内存上限maxmemory时使用LRU等删除策略释放空间。
  • 防止所用内存超过服务器物理内存。

config set maxmemory 6GB //动态设置命令

内存优化
缩减键值对象
  • 首先应该在业务上精简业务对象,去掉不必要的属性避免存储无效数据。
  • 其次在序列化工具选择上,应该选择更高效的序列化工具来降低字节数组大小
共享对象池

在满足需求的前提下,尽量使用整数对象以节省内存。

注意:当设置maxmemory并启用LRU相关淘汰策略如:volatile-lru,allkeys-lru时,Redis禁止使用共享对象池

LRU算法需要获取对象最后被访问时间,以便淘汰最长未访问数据,每个对象最后访问时间存储在redisObject对象的lru字段。对象共享意味着多个引用共享同一个redisObject,这时lru字段也会被共享,导致无法获取每个对象的最后访问时间。

如果没有设置maxmemory,直到内存被用尽Redis也不会触发内存回收,所以共享对象池可以正常工作

查看内存命令

info memory

used_memory:489805456
used_memory_human:467.11M
used_memory_rss:561930240
used_memory_rss_human:535.90M
used_memory_peak:493959760
used_memory_peak_human:471.08M
used_memory_peak_perc:99.16%
used_memory_overhead:72105636
used_memory_startup:803008
used_memory_dataset:417699820
used_memory_dataset_perc:85.42%
allocator_allocated:489917792
allocator_active:494968832
allocator_resident:505876480
total_system_memory:16658219008
total_system_memory_human:15.51G
used_memory_lua:37888
used_memory_lua_human:37.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.01
allocator_frag_bytes:5051040
allocator_rss_ratio:1.02
allocator_rss_bytes:10907648
rss_overhead_ratio:1.11
rss_overhead_bytes:56053760
mem_fragmentation_ratio:1.15
mem_fragmentation_bytes:72165808
mem_not_counted_for_evict:2726
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:186846
mem_aof_buffer:2726
mem_allocator:jemalloc-5.1.0
active_defrag_running:0
lazyfree_pending_objects:0

需要重点关注的指标有:used_memory_rss和used_memory以及它们的比值mem_fragmentation_ratio。

  • 当mem_fragmentation_ratio>1时,说明used_memory_rss-used_memory多出的部分内存并没有用于数据存储,而是被内存碎片所消耗,如果两者相差很大,说明碎片率严重。
  • 当mem_fragmentation_ratio<1时,这种情况一般出现在操作系统把Redis内存交换(Swap)到硬盘导致,出现这种情况时要格外关注,由于硬盘速度远远慢于内存,Redis性能会变得很差,甚至僵死。