Redis基础数据结构--string(字符串)

2020-03-30  本文已影响0人  酷癫

Redis有5种基础数据结构,分别是:string(字符串),list(链表),hash(字典),set(集合),zet(有序链表)。

string(字符串)

Redis中的字符串是一个可修改的字符串,在内存中以字节数组的形式存储,字符串也叫做 Simple Dynamic String,结构如下:

struct SDS<T> {
  // 数组容量
  T capacity; 
   // 数组长度
  T len;
  // 特殊标识位
  byte flags; 
  // 数组内容
  byte[] content;
}

其中,content存储的是真正的字符串内容,capacity表示所分配的数组长度,len表示字符串的长度,当数组没有冗余空间,追加内容时会分配新的数组,将旧数组中的内容拷贝出来,再append新的内容。

redis规定字符串的最大长度为512MB,创建字符串时len和capacity一样长,不分配新的冗余空间。

embstr vs raw

redis的字符串有两种存储方式,在长度特别短的时候,用emb形式存储,当长度超过44时,使用raw形式存储。这两种存储方式结构如下:

embstr vs .png

为什么长度为44?

1.先看下redis的对象头结构

 struct RedisObject {
    int4 type; // 4bits
    int4 encoding; // 4bits
    int24 lru; // 24bits
    int32 refcount; // 64bits
    void *ptr; // 64bits
} robj;

整个RedisObject对象头需占16个字节。

2.从文章开头我们可以看到,SDS的结构使用的是范型,当字符串比较短时,len和capacity可以使用byte和short表示,所以最小的对象头大小为content的长度+3,结构如下:

struct SDS {
   // 1byte
  int8 capacity; 
  // 1byte
  int8 len; 
  // 1byte
  int8 flags; 
  // 内联数组,长度为 capacity 
  byte[] content; 
}

redis为容纳一个完整的 embstr 对象,内存分配器最少会分配 32 字节的空间,如果字符串再稍微长一点,那就是 64 字节的空间。如果总体超出了 64 字节,Redis 认为它是一个大字符串,不再使用 emdstr 形式存储,而该用 raw 形式。

存储字符串长度计算如下:
RedisObject = type(4bits)+encoding(4bits)+LRU(24bits)+refcount(64bits)+ptr(64bits);
SDS = capacity(8bits)+len(8bits)+flags(8bits)+content;
content剩余最多的长度只有45(64-19),而content中的字符串又是已 \0结尾,所有 embstr最大的字符串长度为44。

扩容策略

字符串的长度在小于1M时,扩容采用加倍策略,当长度大于1M时,为避免加倍的冗余空间过大而导致浪费,每次分配只会多1M的冗余空间。

上一篇下一篇

猜你喜欢

热点阅读