redis内存消耗
内存使用统计
关注used_memory_rss(操作系统)和used_memory_rss(存储数据内存占用量)和其比值。
当比值>1,内存碎片
<1,存在swap,redis性能下降
内存消耗划分
rss = 自身内存+对象内存+缓冲内存+内存碎片
3kb = 800kb + ...
1.对象内存
存储键值对
2.缓冲内存
客户端缓冲(输入缓冲区max=1gb,输出可控)
复制积压缓冲区(一个主节点只有一个缓冲区,设置100mb,有效避免全量复制。在RBD中后续命令溢出则全量复制)
AOF缓冲区(小)
3.内存碎片
安全重启
子进程内存消耗
根据期间写入命令量决定、允许内核分配所有的物理内存(sysctl vm.overcommit_memory = 1 )、关闭THP(大页)
内存管理
设置内存上限(maxmemory)
用于缓存,当超过上限后使用LRU策略淘汰,防止内存超过服务器内存
预留一部分防止内存碎片
动态调整内存上限
在线迁移数据或通过复制切换服务器来扩容
内存回收策略
- 删除到期的键
惰性删除:读取时判断并删除超时的键(内存泄漏,一直没被读取释放)
定时任务删除:每秒抽样选择快慢模式 - 内存使用上限触发内存溢出控制策略
- noeviction:不删除,拒绝写入 OOM command not allowed when used memo
- volatile-lru: 删除设置了expire的键
- allkeys-lru:没设置expire的键也删除(纯缓存服务器)
- 随机删除
- 随机删除设置了过期的键
- 删除最佳要过期的键
每次执行命令都会尝试回收内存
内存优化
值对象定义在redisObj结构体,包括对象类型、内部编码类型、LRU时钟、引用计数器、数据指针(scan+object idletime 查询长时间未被访问的键进行清理,高并发场景中字符串限制在39B内,减少分配次数)
缩减键值对象
key长度减少:缩写
value长度:序列化工具:protostuff、kryo(Snappy压缩json来实现通用数据格式来跨语言和调试)
共享对象池(整数)
0~9999整数对象池(当maxmemory且lru淘汰时,redis禁止共享对象池)
字符串优化
- 采用SDS字符串,预分配内存(预分配一倍或者1mb)(减少字符串修改操作如append和setrange,直接修改字符串)
- 字符串重构,将json数据转为hash结构,hmget和hmset支持部分读写(hash要采用ziplist,即连续内存结构,而不是hashtable)
- 编码优化,redis不支持编码回退
ziplist{
[zlbytes字节长度]
[zltail尾节点偏移量]
[zllen压缩链表节点数量]
[entry长度根据实际存储数据]=》{entry}[前一个节点所占空间,用于反向遍历][当前节点编码和长度][值][]
[entry]
...
[zlend列表结尾]}
可以大幅降低内存消耗,但是增加了命令耗时(长度小于1000,元素大小小于512B) - intset编码
set类型编码的一种,存储有序不重复的整数集(编码,元素个数,元素数组)
控制键的数量
根据键的规模分组映射(关键点:1、ziplist 2、长度控制在1k以内 3、存储小对象 4、预估键规模 5、调整参数)1048480=》hash:1948 field:480
标签:编码,删除,对象,redis,消耗,内存,字符串 From: https://www.cnblogs.com/bluebubbleyhbgsj/p/18303357