第8章 理解内存

理解Redis内存消耗,管理和优化。

1. 内存消耗

1.1 内存使用统计

通过info memory命令获取内存相关指标,重点指标:

used_memory_rss  //操作系统角度Redis进程占用的物理内存总量
used_memory     //Redis内部存储的所有数据内存占用量
mem_fragmentation_ratio    //内存碎片率 >1时说明多出的内存被内存碎片消耗,<1时则要注意操作系统swap到硬盘

1.2 内存消耗划分

第8章 理解内存_第1张图片
Redis内存消耗划分.jpg
  • 对象内存:存储用户所有key-value数据
  • 缓冲内存:客户端缓冲,复制积压缓冲区,AOF缓冲区
  • 内存碎片:默认内存分配器:jemalloc

1.3 子进程内存消耗

  • Redis产生的子进程并不需要1倍的父进程内存(copy-on-write),实际消耗根据写入命令量决定
  • 需要设置sysctl vm.overcommit_memory=1允许内核可以分配所有物理内存,放置fork失败
  • 排查当前系统是否开启THP,建议关闭,防止内存过度消耗

2. 内存管理

2.1 设置内存上限

  • 用于缓存场景,超出上限时使用LRU释放空间
  • 防止所用内存超过服务器物理内存

2.2 动态调整内存上限

config set maxmemory

动态修改内存,伸缩配置

2.3 内存回收策略

  • 删除到达过期时间的键对象:惰性删除(客户端读取时检查删除)/定时任务删除
  • 内存溢出控制策略:
    1. noeviction:默认,拒绝写入
    2. volatile-lru:LRU删除超时键
    3. allkeys-lru:LRU删除所有键
    4. allkeys-random:随机删除所有键
    5. volatile-random:随机删除过期键
    6. volatile-ttl:删除最近将要过期数据

注意:频繁执行回收内存成本很高,如果有从节点会同步,导致写放大

3. 内存优化

3.1 redisObject对象

第8章 理解内存_第2张图片
redisObject内部结构.jpg
  • type:数据类型
  • encoding:内部编码类型
  • lru:最后一次被访问的时间
  • refcount字段:记录当前对象被引用的次数
  • *ptr字段:与对象的数据内容相关

3.2 缩减键值对象

降低Redis内存使用最直接的方法:缩减key和value的长度
选择高效的序列化工具

3.3 共享对象池

共享对象池是指Redis内部维护[0-9999]整数对象池。创建大量的整数类型redisObject存在内存开销。
使用共享对象池,相同的数据内存使用降低30%以上。

3.4 字符串优化

Redis有自己内部的动态字符串:


第8章 理解内存_第3张图片
字符串结构体SDS.jpg

由于预分配机制,同样的数据追加后内存消耗非常严重。(追加后预分配一倍容量)
字符串重构:对json这种,可以使用hash这样的二级结构来饥饿省内存,支持字段的部分读取修改

3.5 编码优化

不同编码实现效率和空间的平衡
编码类型转换过程不可逆,只能从小内存编码向大内存编码转换。

3.6 控制键的数量

hash结构降低键数量分析

  1. 根据键规模在客户端通过分组映射到一组hash对象中
  2. hash的field可用于记录原始key字符串
  3. hash的value保存原始值结构

hash键和field键的设计:

  1. 键的离散度高时,按照字符串位截取
  2. 键离散度低,用哈希算法打散键,哈希field存储键的原始值
  3. 尽量减少hash键和field的长度,如使用部分键内容

你可能感兴趣的:(第8章 理解内存)