Redis底层数据结构

Redis对象

typedef struct redisObject {
	/*数据类型*/
	unsigned type:4;
	/*编码方式*/
	unsigned encoding:4;
	/*最后一次被访问的时间,保存了一个24位时间戳*/
	unsigned lru:LRU_BITS;
	/*记录了键值被引用的数量*/
	int refcount;
	/*指向底层数据结构的指针*/
	void *ptr;
} robj

数据类型 type

代码数据类型最大值备注
0OBJ_STRINGstring512 M
1OBJ_LISTlist232 - 1 个
2OBJ_SETset232 - 1 个场景:好友集合,粉丝集合
3OBJ_ZSETzset232 - 1 个场景:排行榜
4OBJ_HASHhash223 - 1 个
5OBJ_MODULEmodule模块 ( redis >= 4.0 ),加载外部模块进行功能性扩展
6OBJ_STREAMstream流 ( redis >= 5.0.0 ),支持多播的可持久化消息队列

备注:redis < 3.2 编码方式以“REDIS_”开头,不是“OBJ_”


编码方式 encoding

代码备注
0OBJ_ENCODING_RAW简单动态字符串
1OBJ_ENCODING_INT整数值
2OBJ_ENCODING_HT字典
3OBJ_ENCODING_ZIPMAP压缩字典 ( redis < 2.6 )
4OBJ_ENCODING_LINKDELIST双端链表 ( redis < 3.2 )
5OBJ_ENCODING_ZIPLIST压缩列表
6OBJ_ENCODING_INTSET整数集合
7OBJ_ENCODING_SKIPLIST跳跃表
8OBJ_ENCODING_EMBSTRembstr编码的简单动态字符串
9OBJ_ENCODING_QUICKLIST快速链表 ( redis >= 3.2 )
10OBJ_ENCODING_STREAM流 ( redis >= 5.0.0 )
11OBJ_ENCODING_LISTPACK紧凑列表 ( redis >= 7.0.0 )

备注:redis < 3.2 编码方式以“REDIS_”开头,不是“OBJ_”


字符串编码类型

  • int
    存储 8 个字节的长整型(long,263-1)
  • embstr
    代表 embstr 格式的 SDS,存储小于 44 个字节的字符串。
    RedisObject 对象头和 SDS 对象连续存在一起,使用 malloc 方法分配一次内存空间
  • raw
    存储大于 44 个字节的字符串,需要分配两次内存空间(分别为 Redis Object 和 SDS 分配空间)
    备注:3.2 版本之前是 39 个字节

底层数据结构

动态字符串 sds

redis版本 < 3.2

embstr : redisObject(16)+sds{char(39) + int(4*2=8) + 1(结尾的\0)} = 64字节

typedef struct sdshdr{
     //记录buf数组中已使用字节的数量
     //等于 SDS 保存字符串的长度
     unsigned int len;
     //记录 buf 数组中未使用字节的数量
     unsigned int free;
     //字节数组,用于保存字符串
     char buf[];
}

redis版本 >= 3.2

  • sdshdr5:25 = 32 byte

  • sdshdr8:28 = 256 byte

  • sdshdr16:216 = 65536 byte = 64KB

  • sdshdr32:232 = 65536 byte = 4GB

  • sdshdr64:264 byte = 224 TB = 16 EB

embstr : redisObject(16)+sds{char(44) + uint8_t(1*2=2) + char(1) + 1(结尾的\0)} = 64字节

/*以sdshdr8为例*/

struct __attribute__ ((__packed__)) sdshdr8 {
    //当前字符数组的长度
    uint8_t len;
	//当前字符数组总共分配的内存大小
    uint8_t alloc; 
	//当前字符数组的属性,用来标识sdshdr5、sdshdr8、sdshdr16、sdshdr32、sdshdr64
    unsigned char flags;
	//字符串真正的值
    char buf[];
};

链表 list

typedef struct list{
     //表头节点
     listNode *head;
     //表尾节点
     listNode *tail;
     //节点值复制函数
     void (*dup) (void *ptr);
     //节点值释放函数
     void (*free) (void *ptr);
     //节点值对比函数
     int (*match) (void *ptr,void *key);
     //链表所包含的节点数量
     unsigned long len;
}list;
typedef  struct listNode{
       //前置节点
       struct listNode *prev;
       //后置节点
       struct listNode *next;
       //节点的值
       void *value;  
}listNode
/*迭代器*/
typedef struct listIter {
    listNode *next;
    int direction;
} listIter;

字典 hashtable

typedef struct dictht{
     //哈希表数组
     dictEntry **table;
     //哈希表大小
     unsigned long size;
     //哈希表大小掩码,用于计算索引值
     unsigned long sizemask;
     //该哈希表已有节点的数量
     unsigned long used;
 
}dictht
typedef struct dictEntry{
     void *key;
     union{
          void *val;
          uint64_tu64;
          int64_ts64;
     }v;
     struct dictEntry *next;
}dictEntry

跳跃表 skiplist

typedef struct zskiplistNode {
 
     struct zskiplistLevel{
 
       struct zskiplistNode *forward;
 
       unsigned int span;
 
     }level[];
     struct zskiplistNode *backward;
     double score;
     robj *obj;
} zskiplistNode;
typedef struct zskiplist{
     //表头节点和表尾节点
     structz skiplistNode *header, *tail;
     //表中节点的数量
     unsigned long length;
     //表中层数最大的节点的层数
     int level;
}zskiplist;

整数集合 intset

typedef struct intset{
     //编码方式
     uint32_t encoding;
     //集合包含的元素数量
     uint32_t length;
     //保存元素的数组
     int8_t contents[];
}intset

压缩列表 ziplist

/* Each entry in the ziplist is either a string or an integer. */
typedef struct {
    /* When string is used, it is provided with the length (slen). */
    unsigned char *sval;
    unsigned int slen;
    /* When integer is used, 'sval' is NULL, and lval holds the value. */
    long long lval;
} ziplistEntry;

紧凑列表 listpack

listpack作为ziplist的替代者,它的内存布局、实现原理和ziplist非常相似。
listpack内存更紧凑,实现更简洁。

/* Each entry in the listpack is either a string or an integer. */
typedef struct {
    /* When string is used, it is provided with the length (slen). */
    unsigned char *sval;
    uint32_t slen;
    /* When integer is used, 'sval' is NULL, and lval holds the value. */
    long long lval;
} listpackEntry;

数据类型对应的底层数据编码

类型编码方式版本条件
OBJ_STRINGOBJ_ENCODING_INT8个字节的长整型
OBJ_STRINGOBJ_ENCODING_EMBSTR小于等于44字节
OBJ_STRINGOBJ_ENCODING_RAW大于44字节
OBJ_LISTOBJ_ENCODING_ZIPLISTredis < 3.2元素个数少于512,且value小于等于64字节
OBJ_LISTOBJ_ENCODING_LINKEDLISTredis < 3.2元素个数大于512,或者value大于64字节
OBJ_LISTOBJ_ENCODING_QUICKLISTredis >= 3.2全部
OBJ_SETOBJ_ENCODING_INTSET集合中的元素都是整数且元素个数小于512(默认值)
OBJ_SETOBJ_ENCODING_HT其他
OBJ_ZSETOBJ_ENCODING_SKIPLIST元素个数大于128(默认),或者value大于64字节
OBJ_ZSETOBJ_ENCODING_ZIPLISTredis < 7.0元素个数少于128(默认),且value小于等于64字节
OBJ_ZSETOBJ_ENCODING_LISTPACKredis >= 7.0元素个数少于128(默认),且value小于等于64字节
OBJ_HASHOBJ_ENCODING_HTfiled的个数大于512,或者value大于64字节
OBJ_HASHOBJ_ENCODING_ZIPLISTredis < 7.0filed的个数少于512,且value小于等于64字节
OBJ_HASHOBJ_ENCODING_LISTPACKredis >= 7.0filed的个数少于512,且value小于等于64字节
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值