Redis内存

Redis内存消耗:自身内存 + 对象内存 + 缓冲内存 + 内存碎片

  1. 自身内存:Redis进程自身内存占用量很小,大约在3.8M左右。
  2. 对象内存:sizeof(keys) + sizeof(values),键和值的内存都需要关注
  3. 缓冲内存:主要包括客户端缓冲、复制积压缓冲区、AOF缓冲区
    • 客户端缓冲:指所有接入到Redis服务器TCP连接的输入输出缓冲,超过1G会自动断开
    • 复制积压缓冲区:用于实现部分复制功能补救措施的缓冲区
    • AOF缓冲区:Redis重写期间保存最近的写入命令,消耗内存取决于AOF重写时间及写入命令量
  4. 内存碎片:Redis默认使用jemalloc分配器、可选glibc、tcmalloc,为了更好的管理和复用内存,一般采用内存块进行分配,通常采用数据对齐或安全重启处理内存碎片超标情况

子进程内存消耗:子进程fork后与父进程享有同一物理内存,AOF/RDB期间父进程处理写请求时会复制出请求的页副本进行写操作,子进程依然读取父进程快照

  1. Redis fork期间产生的子进程需要消耗的内存由持久化期间写入命令量决定
  2. 设置sysctl vm.overcommit_memory = 1允许内存分配所有的物理内存
  3. 排查当前系统是否支持THP,防止copy-on-write期间内存过度消耗

内存管理:Redis通过控制内存上限和回收策略实现内存管理。

  1. 设置内存上限:Redis使用maxmemory参数限制最大可用内存
    • 用于缓存场景,超出上限maxmemory后使用LRU等删除策略释放空间
    • 防止所有内存超过服务器物理内存,需要注意由于内存碎片的存在,实际消耗会比maxmemory更大
  2. 动态调整内存上限
    • 当Redis实例设置maxmemory不合理时,可以通过config set maxmemory进行修改
  3. 内存回收策略
    • 删除到达过期时间的键对象:惰性删除(读取到超时的键就删除,减少TTL的消耗)和定时任务删除(每秒执行十次,根据键的过期比例使用快慢两种方式回收键)
    • 内存溢出控制策略(maxmemory-policy):noeviction(不删除,拒绝写入)、volatile-lru(LRU删除设置了超时时间的属性)、allkeys-lru(LRU删除不管超时)、allkeys-random(随机删除所有键)、volatile-random(随机删除过期键)、volatile-ttl(根据对象的ttl属性删除即将过期的数据)

内存优化

  1. RedisObject:Redis存储的所有值对象在内部均定义为redisObject结构体
    • 结构:type(当前对象使用的数据类型)、encoding(Redis内部编码类型)、lru(记录对象的最后一次被访问时间)、refcount(记录当前对象被引用的次数)、* ptr(对象的数据内容相关)
  2. 缩减键值对象
    • key长度通过缩写减短、value长度通过对象序列化成二进制或压缩
  3. 共享整数对象池
    • 由于创建某些大对象的开销过高,因此可以使用共享对象池,对于某些相同值的大对象公用一份数据。
    • 共享对象池与maxmemory + LRU策略冲突,因为多个对象共享一个RedisObject,无法获取每个对象的LRU。
    • 使用ziplist压缩的值也无法使用整数对象池,判断成本过高
  4. 字符串优化
    • 字符串结构:Redis实现了自己的字符串结构SDS,结构体内包含len(已用字节长度)、free(未用字节长度)、buf[](字节数组)。采用惰性删除机制,内部实现空间预分配,降低内存再分配次数。
    • 预分配机制:防止不断重新分配内存和字节数据拷贝带来的消耗,但会造成内存浪费
    • 字符串重构:不一定将数据作为字符串整体存储,存储成hash之类的ziplist编码的二级结构也有利于节约内存
  5. 编码优化:即数据存储的底层数据结构实现
    • 编码在Redis写入数据时会自动从小的内存编码向大的内存编码转换
    • ziplist编码:可以节约大量的内存,但因为链表的存在读写成本高,命令操作会更加耗时
    • intset编码:存储有序、不重复的整数集,内存占用量小且性能高,插入时间复杂度O(n),查询时间复杂度O(log(n))。
  6. 控制键的数量
    • 将大量的键分组映射到hash中可以节省内存

Redis内存优化技巧总结:

  1. hash类型节省内存仅在使用ziplist编码时生效,使用hashtable反而会增加内存用量
  2. ziplist长度需要控制在1000以内,否则长列表会使读取数据时CPU严重消耗
  3. value越小,压缩及性能优化效果越明显
  4. 预估键规模,确定每个hash结构需要存储的元素数量,根据hash长度和元素大小,调整hash-max-ziplist-entries和hash-max-ziplist-value参数,确保ziplist编码的使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值