Redis内存优化

内存预估

最近项目进行数据迁移,需要申请一个redis,需要预估下内存,项目里主要是string类型的value,因此只查询了string类型的存储模型。

一个简单的set命令最终会产生4个消耗内存的结构,中间free掉的不考虑

1. 1个dictEntry结构,24字节(键、值、下个节点指针),负责保存具体的键值对;jemalloc会分配32字节的内存块。

2. 1个redisObject结构,16字节(类型、编码、lru时间、引用计数、数据指针),用作val对象;jemalloc会分配16字节的内存块。

3. 1个SDS结构,(key长度 + 9)字节,用作key字符串;9包含了len、free、/0

4. 1个SDS结构,(val长度 + 9)字节,用作val字符串;

当key个数逐渐增多,redis还会以rehash的方式扩展哈希表节点数组,即增大哈希表的bucket个数,每个bucket元素都是个指针(dictEntry*),占8字节,bucket个数是超过key个数向上求整的2的n次方。

真实情况下,每个结构最终真正占用的内存还要考虑jemalloc的内存分配规则,综上所述,string类型的容量评估模型为:

总内存消耗 = (dictEntry大小 + redisObject大小 + key_SDS大小 + val_SDS大小)× key个数 + bucket个数 × 指针大小

假如我有1000个key,每个key平均54字节,每个value平均103字节,那一共占用内存:

(32 + 16 + 63 + 111)* 1000 + 1024 * 8 = 230192字节

内存优化

我分析了项目里大部分key的存储格式有六种场景:scene_A_{userID}、scene_B_{userID}、scene_C_{userID}、scene_D_{userID}、scene_E_{userID}、scene_F_{userID}

根据项目WAU(两千万)计算,预计有2000w用户id * 6 = 1.2亿个key,占用内存30G,由于公司降本增效,需要优化redis的内存。

方案一:

将key的格式改造成hash形式:scene_{userID}: A: value B:value C:value D:value... ,key的数量直接从1.2亿减少为2000w,占用内存预估20G,降低了10G。

方案二:

将key的格式改造成hash形式:scene_A: {userID}:value,key的数量只需要6个,占用内存17G,但是filed的数量会达到2000w个,属于大key,需要对value进行序列化/压缩,压缩率大概为30%,由于该key属于热点数据,每次获取都需要对value进行解压,同时大key对redis的IO也造成负担,耗时较大,不太合理,因此我选择了方案一。

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容