【Redis】内存

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Francis123580/article/details/82503064

内存消耗

Redis进程内消耗包括:自身内存 + 对象内存 + 缓冲内存 + 内存碎片
其中自身内存消耗非常小,占3M左右,主要是其它3种内存

内存消耗划分

  • 对象内存是Redis内存占用最大一块
  • 缓冲内存包括 客户端缓冲、复制积压缓冲区、AOF缓冲区
  • 内存碎片:频繁更新操作、大量过期键删除会造成内存碎片,通过数据对齐和安全重启可以降低碎片

子进程内存消耗

  • Redis产生的子进程并不需要消耗1倍父进程内存,实际消耗根据写入命令量决定
  • 需要设置允许内核可以分配所有的物理内存,防止Redis进程执行fork时因系统剩余内存不足而失败
  • 排查当前系统是否支持并开启THP,建议关闭,防止copy-on-write期间内存过度消耗

内存管理

设置内存上限

  • Redis使用 maxmemory 参数限制最大可用内存
  • 因为内存碎片率的存在,实际使用可能要大一些,要防止内存溢出
  • 该设置用于缓存场景,超过后使用LRU等删除策略释放空间
  • 该设置防止所用内存超过服务器物理内存

动态调整内存上限

  • 执行 config set maxmemory 命令进行动态修改
  • 通过动态修改maxmemory,可以实现当前服务器下动态伸缩Redis内存的目的

内存回收策略

  • 删除过期对象:惰性删除 / 定时任务删除
  • 内存溢出控制策略:noeviction(默认)、volatile-lru(LRU删除超时键)、allkeys-lru(LRU删除键)、allkeys-random(随机删除所有键)、volatile-random(随机删除过期键)、volatile-ttl(删除最近将要过期键)

内存优化

redisObject 对象

  • 同一个对象采用不同的编码实现对内存占用有明显差异
  • 可以使用 scan + object idletime 命令批量查询长时间未访问键,清理以降低内存
  • 通过对象引用次数回收内存,为0时可以安全回收当前对象
  • 建议字符串长度控制在39字节以内,减少redisObject内存分配

缩减键值对象

  • key长度:完整描述业务的情况下,键值越短越好
  • value长度:把业务对象序列化成二进制数组放入Redis,另外避免无效数据

共享对象池

  • 尽量使用整数对象以节省内存,因为Redis内部维护了一个整数对象池
  • 共享对象池与maxmemory+LRU冲突
  • ziplist编码的值对象,无法使用共享对象池

字符串优化

  • 字符串采用预分配方式防止修改操作需要不断重分配内存和拷贝,造成内存浪费
  • 尽量减少字符串频繁修改操作,改为直接用set修改字符串,降低预分配内存浪费和内存碎片化
  • 字符串重构:json数据可以使用hash结构,可以部分修改

编码优化

  • 使用 config set 命令设置编码相关参数满足使用压缩编码的条件
  • 性能要求较高的场景使用ziplist,长度不要超过1000,每个元素大小控制在512字节内
  • 使用intset编码的集合时,保持整数范围一致,防止个别大数触发集合升级,产生内存浪费

控制键的数量

  • 利用hash结构降低键的数量
  • 同样数据使用ziplist编码的hash比string类型的节约内存
  • hash-ziplist类型比string写入耗时,但随着value空间减少,耗时降低
  • ziplist长度需要控制在1000以内,长列表会导致CPU消耗严重
  • hash重构后所有键无法使用超时和LRU淘汰机制自动删除
  • 对于大对象(1KB),使用hash-ziplist结构控制反而得不偿失
  • 对于大量小对象的存储场景,非常适合使用hash-ziplist来控制键来降低内存

 
 

猜你喜欢

转载自blog.csdn.net/Francis123580/article/details/82503064