使用内存包含:
自身内存:一般没多少,几百KB ; Lua内存 ;内存碎片
缓冲内存:复制时的复制挤压缓冲区及客户端交互的输出缓冲区;优化就是调大小、限制连接数
对象内存:占主要部分,数据使用内存;优化就是正确用数据结构
概要:1共享对象、2键值对管理、3过期策略、4淘汰机制、5内存最佳实践(选择正确数据结构、避免大key、热key)
一、共享对象
启动时创建10000个redisObject,代表1-10000整型,一直保存内存中,其他对象用时共享使用。LRU成员没用,没有其他开销。
二、键值对管理
用redisDb表示数据库,底层用字典类型,单redis可设置16个这样DB;select选择,不同DB互不影响。
2.1 过期Key清理
dict结构(dict)存储键值对象;复用Key、Value对象,没额外内存开销。
记录设过期时间的键值对,固定条件,或者CPU空闲,自动执行del清理过期Key。最高25%时间删除,其他时间管理Redis任务。
过期Key清理算法(redis.c/activeExpireCycle()函数实现):
(1)遍历所有的DB,随机取20个,过期,则删除。
(2)有大于5个过期,则重复上一步;否则遍历下一个DB
清理过程中,到时间限制,退出
2.2 异步删除
4.0对DEL/FLUSHDB/FLUSHALL引入异步处理。FLUSHALL/FLUSHDB 加了一个 ASYNC 参数,同时新增 UNLINK 来表示异步化的删除命令。unlike命令实现:
三、过期策略(用2+3)
没设置时间,缓存永不过期;设置又想永不过期,用persist key
三种方式:定时删、懒汉式删、定期删
2.1定时删
设置过期时间时,为key创建定时器,key过期时删key
优点:内存尽快释放
缺点:key多占CPU时间、定时器创建耗时,影响性能
2.2懒汉式删
用key获取值时检查,过期删,返回null。优缺点:占CPU少,占内存
2.3定期删
每隔一段时间删。限制删时长和频率,减少前两个缺点(折中)
四、淘汰机制
volatile-lru:已设置过期时间最近最少用
volatile-ttl:已设置过期时间选要过期
volatile-random:已设置过期时间任意选
allkeys-lru:最近最少使用淘汰
allkeys-random:任意选数据淘汰
no-enviction:禁止淘汰数据
淘汰算法:
遍历所有DB,按照淘汰策略挑选一个Key淘汰;
若是lru或ttl,随机取n个样本(默认为5,可配置),选出最佳值淘汰;
超过允许值,重复上面
五、内存最佳实践
4.1选择正确数据结构
String用整数,浮点型成整数。
量大重要:字符串类合理拆分,对压缩列表转换条件进行放宽
存Key-Value时,object后加整数作为ID,数据量大,取模优化,相同前缀Key做hash。db空间相当大的哈希表,把本来分配给整个db空间的Key,按照不同的前缀分成小的哈希表,里面数据小,用压缩列表来保存。
4.2 避免BigKey和HotKey
(1)BigKey:https://www.jianshu.com/writer#/notebooks/27207290/notes/79614564
(2)HotKey
集群没合理用:访问键值集中,远高于其他,造成单点故障,导致集群不可用
拆分HotKey,平均散落各实例
4.3 合理的设置过期时间
频繁删除,会引起阻塞。
4.4 命名规范
没有MySQL隔离级别、MVCC等数据隔离特性,命名额外重要。
用SDS来保存Key,大小受String限制,最大512M。创建时根据长度选择底层的实现编码。Key设计最好简介、明了。
用业务名前缀,防止Key冲突;不能用特殊字符!
https://blog.csdn.net/xiangnan129/article/details/54928672