String类型底层结构
使用的底层结构为简单动态字符串(Simple Dynamic String SDS)。
typedef char *sds;
struct sdshdr {
int len;
int free;
char buf[];
};
简单动态字符串内存长度:

len:记录buf已使用的长度,len长度为4byte;
alloc:记录buf实际分配的长度,alloc长度为4byte;
buf:字节数组,保存实际数据,“\0”表示数据结束,额外增加1个字节开销。
String类型除了SDS内存使用外,还有RedisObject结构体。
RedisObject结构体使用8byte存储元数据,使用8byte存储数据指针,数据指针指向具体数据所在位置。

struct redisObject {
unsigned type:4;
unsigned encoding:4;
unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
* LFU data (least significant 8 bits frequency
* and most significant 16 bits access time). */
int refcount;
void *ptr;
};
结构体RedisObject定义了5个属性:type、enconding、lru、refcount和*prt。
- type:当前值对象的数据类型
| 有序集合对象 | 对象的名称 |
|---|---|
| REDIS STRING | 字符串对象 |
| REDIS LIST | 列表对象 |
| REDIS HAST | 哈希对象 |
| REDIS SET | 集合对象 |
| REDIS ZSET | 有序集合对象 |
查看key type:
> set testkey1 test
OK
> type testkey1
string
- encoding:当前值对象底层编码类型
| 类型 | 编 码 | 对 象 |
|---|---|---|
| REDIS STRING | REDIS ENCODING INT | 使用整数值实现的字符串对象 |
| REDIS STRING | REDIS ENCODING EMBSTR | 使用embstr编码的简单动态字符申实现的字符串对象 |
| REDIS STRING | REDIS ENCODING RAW | 使用简单动态字符申实现的字符串对象 |
| REDIS LIST | REDIS ENCODING ZIPLIST | 使用压缩列表实现的列表对象 |
| REDIS LIST | REDIS ENCODING LINKEDLIST | 使用双端链表实现的列表对象 |
| REDIS HASH | REDIS ENCODING ZIPLIST | 使用压缩列表实现的哈希对象 |
| REDIS HASH | REDIS ENCODING HT | 使用字典实现的哈希对象 |
| REDIS SET | REDIS ENCODING INTSET | 使用整数集合实现的集合对象 |
| REDIS SET | REDIS ENCODING HT | 使用字典实现的集合对象 |
| REDIS ZSET | REDIS ENCODING ZIPLIST | 使用压缩列表实型能有序篇合对象 |
| REDIS ZSET | REDIS ENCODING SKIPLIST | 使用跳跃表和字典实现的有序集合对象 |
查看key encoding:
> set testkey1 test
OK
> object encoding testkey1
embstr
> set testkey2 7
OK
> object encoding testkey2
int
- Iru:存储最后一次使用此对象的时间等信息。当redis内存回收算法设置为volatile-lru或者allkeys-lru时候redis会优先释放最久没有被访问的数据。
- int refcount:记录对象引用次数。用于共享计数,类似于jvm的引用计数垃圾回收算法,当refcount为0时,表示没有其它对象引用,可以进行释放此对象。
- void *ptr:指向真正底层数据结构的指针。
Redis针对不同的数据类型,做了一些优化:
1.如果是Long类型整数,ptr为整数数据,非指针,目的是为了节省内存,这种内存布局方式称为int编码方式;
2.如果是字符串类型,并且长度小于或等于44byte时,RedisObject中的元数据、ptr、SDS为一块连续内存,目的为了避免内存碎片,这种内存布局方式称为embstr编码方式;
3.如果字符串类型大于44byte,ptr指向SDS内存空间,这种内存布局方式称为raw编码方式。
int编码、embstr编码、raw编码方式结构如下:

Redis核心技术-数据结构1-底层结构中说的key和value存储在哈希表dictEntry结构体中,dictEntry结构体需要24byte,但是由于jemalloc内存分配方式规则,dictEntry实际内存为32byte。内存结构如下:

Redis使用jemalloc库分配内存,jemalloc分配内存时,根据申请内存字节数N,计算比N大的字节数S,S取值最接近2的次方数。
例如N=24,S取值2的5次方=32。类似JVM中的内存大小分配。
由此可以计算出一个key和value最少需要多大内存?
key和value都是Long整数,都使用int编码,需要64byte,其中dictEntry32byte(24byte+8byte填充)、key值16byte、value值16byte;
参考:
https://www.cnblogs.com/monkey-code/p/13157908.html
本文详细介绍了Redis中String类型的底层实现,包括SimpleDynamicString(SDS)结构和RedisObject结构体。SDS结构包含len和free字段,以及buf字节数组。RedisObject则包含type、encoding、lru和refcount属性。字符串类型根据长度采用int编码、embstr编码或raw编码,以优化内存使用。此外,文章还提到了内存分配策略,如jemalloc的内存分配规则,并讨论了key-value存储在哈希表中所需的内存大小。
1512

被折叠的 条评论
为什么被折叠?



