list是否包含string_String类型的内存开销有多大,我想去看看

重点内容:

02f82e0c744908df4874a2c5f1bb3b24.png

String类型的键值特点:一键对一值;可保存二进制字节流,如:结构体序列化为二进制字节数组,将字节数组作为键的值保存。 采用String类型保存数据时需要额外内存来记录数据长度、空间使用等元数据信息。当实际数据较小时,元数据的内存开销显得比较大,即:相对实际数据,元数据内存比重较大。

1.String类型的内存布局

先介绍几个Redis底层数据结构,是如何支撑String类型的实现。从中可以了解到哪部分内存属于额外的内存开销。

1.1 SDS结构体

SDS结构体:简单动态字符串,包含如下字段:

c4c8467b1f18140f271f1d75e96bf561.png

字段说明如下:

字段

描述

备注

len

buf的内存使用字节数,字段占4B。

非实际数据,额外开销

alloc

buf的内存分配字节数,字段占4B,一般大于len。

非实际数据,额外开销

buf

字节数组,保存实际数据,C风格字符串(结尾’\0’)

除SDS结构体中的额外开销,还有RedisObject结构体的额外开销,Redis用它来记录String,List,Hash,Set,Sorted Set等数据类型的元数据(如最后一次访问的时间、被引用的次数等),同时指向实际数据。

1.2 RedisObject结构体

RedisObject结构体,包含如下字段:

d282b3ec0e14e055dfbd6d562fbf0e85.png

字段说明如下:

字段

描述

备注

元数据

8B

非实际数据,额外开销

指针

8B,指向具体数据类型的实际数据

是否额外开销,视编码方式而定

1.3 dictEntry结构体

Redis采用全局哈希表(链式哈希表)保存所有键值对,表元素是一个dictEntry结构体,用来指向一个键值对。每个键值对,Redis都会在底层分配一个dictEntry结构体。该结构体有3个指针字段,用于指向key、value以及下一个dictEntry。

Redis使用的内存分配库jemalloc,在分配内存时,根据申请的字节数N,找一个比N大最接近N2的幂次数作为分配空间,如此可以减少频繁分配的次数。因此,dictEntry结构体会被分配32B。

4879245a6849c47b0c9bdc2c60d8a8f4.png

1.4 编码方式

Redis针对String类型,专门设计3种编码方式来优化内存布局,从而节省内存开销。如下:

保存对象

编码方式

存储优化

long类型整数

int编码

RedisObject的指针字段用于存储数据,不再额外指向实际的数据,有效利用指针的内存开销

字符串数据(<=44B)

embstr编码

RedisObject结构体和SDS结构体的内存布局是连续的,避免产生内存碎片

字符串数据(>44B)

raw编码

SDS结构体的buf数据量较多,分配单独的内存空间,RedisObject结构体的指针字段指向SDS结构体。

3种编码方式示意图如下:

b59a20e2ea693dafafa71edb16cfae1f.png       938ad32eca76fceed977b9e4b5b2e54f.png

595d06d12d062424628236c72bd5766a.png

2.String类型存储示例

127.0.0.1:6379> set STU_201413145 “yang zheng”

4d618942561c7baee7e4a471700e62f5.png

95c130ed1b51998f3a78e24b4c91eba8.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值