Redis的String数据结构详解

对于Redis的String类型的value,采用的是SDS数据结构。但是对于value是8字节的Long类型的value则使用的是int编码。

也就是说,这种一对一,非集合类型的value有俩种编码方式。

  1. value是Long类型的(只要是数字就行),保存方式是int编码
  2. value中有字符,则使用SDS。
  3. 对于SDS也有两种编码,根据字符串长度区分,小于等于44字节则使用embstr。大于则使用raw编码。

SDS结构:

元数据(len(4字节,表示已用长度),alloc(4B,表示已分配实际长度大于len)), buf(字符数组+’/0’结尾)

RedisObject:

描述各个数据结构共同的元数据。比如说最后访问时间,被引用的次数等。每一个value都有一个redisobject,里面有8字节的元数据和8字节的指针,指向他们。

对于String类型的int编码,和embstr、raw编码的内存优化:

  1. 对于int编码,redisobject指针直接赋值为整数数据,省了一个指针的内存开销
  2. 对于embstr,则redisobject和sds是一块连续的内存,也就是说只申请一次,避免碎片
  3. 对于raw则redisobject和sds是分开的,需要申请两次内存。并且指针会指向sds内存。

redis使用一个全局哈希表维护所有数据。而全局哈希表中会有一个dictEntry结构体,类似hashmap中的node。来表示一个键值对。有三个指针key,value,next都是4字节。且redis使用的内存分配库是jemalloc,类似hashmap的容量,会找一个最接近需要字节数的2的n次幂来分配内存。24也就是分配32字节。

总结:

Sting类型会消耗很多字节来保存元数据。假设一个2字节的key和5字节的value 数据,需要 9 (len+alloc+buf(’/0’)) + 16(redisobject) + 32(dictEntry结构体 中的key,value,next指针) + 2+5(原始数据消耗)= 64字节。而必要消耗才7字节,用了很多额外保存元数据。

一个10位数的key和10为value数字。redisobject 8字节元数据,8字节Long直接赋值。16字节 key+value就是32字节。对应的DictEntry结构体32字节,加起来也有64字节。

所以String类型很消耗内存。即使是int编码。

可以使用集合类型的压缩列表,要符合压缩列表的编码要求。

除了String类型的内存消耗和它的三种编码之外

依旧有一些优点:

  1. 元数据,len和alloc。比较c语言字符串,len可以让求字符串长度变的简单。并且保证了二进制数据的安全性。c语言字符串需要遍历到’\0’,二进制中可能会有冲突。alloc已经分配的长度,会大于len。保证不需要频繁申请内存。也保证空间的惰性释放。
  2. 使用了buf字符数组,也就是c的字符串的表示。可以使用一部分c的字符串函数。
  3. 空间预分配,也就是多分配一部分内存。规则是:小于1m则*2 大于1m则多分配1m。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值