string类型额外开销
这里以存储10位的int key 对应10位的int value举例。假设key=1000000000,value=9999999999。这里以redis string 类型存储。可能大家以为16个字节就够了(8字节能表示 2的64次方),但实际远远不够。存在三部分额外开销,分别是:SDS结构,RedisOjbect,全局哈希表
SDS结构
当存储的数据中包含字符串,string类型就会使用SDS结构保存数据
buf中存储数据
len使用四个字节表示buf已用长度
alloct使用四个字节表示buf实际使用长度(>=len)
RedisOjbect
存在RedisObject结构是因为,不同的数据类型都有些相同的元数据要进行记录(比如最后一次的访问时间)。RedisObject由两部分组成:8字节元数据 + 8字节指针。
根据SDS和RedisOjbect的关系,出现了三种编码方式。
1.当数据为int时,指针直接赋值为正数,节省了指针的空间开销,称之为int编码。
2.当字符串<=44字节,会生成SDS结构,SDS与RedisOjbect的指针相邻,避免了内存碎片,称之为embstr编码。
3.当字符串>44字节,会生成SDS结构,RedisOjbect的指针指向SDS,称之为raw编码。
全局哈希表
redis会使用全局哈希表保存键值对,其中每一项都是一个dictEntry结构体。
dictEntry由三个(8字节)指针组成,分别指向key,value,next。这样看来会有24字节的开销。由于redis使用的内存分配库是jemalloc(分配2的整数次),所以实际分配了32字节
以10位int的key和10位int的value做例子。由于其是int,所以RedisObject采用int编码。RedisObejct消耗内存 (8 + 8)* 2 = 32,再加上全局哈希表上的32开销。总计64个字节。