Redis对外提供了string,list,hash,set,zet等类型,但是Redis内部针对不同类型存在编码(底层数据结构)的概念,所谓编码就是具体使用哪种底层数据结构来实现。编码不同将直接影响数据的内存占用和读写效率。 使用 object encoding {key} 命令获取编码类型。如下:
redis> set str:1 hello
OK
redis> object encoding str:1
"embstr" # embstr编码字符串
redis> lpush list:1 1 2 3
(integer) 3
redis> object encoding list:1
"ziplist" # ziplist编码列表
Redis针对每种数据类型(type)可以采用至少两种编码方式来实现,下表表示type和encoding的对应关系。
虽然 Redis 是用 C 语言写的,但是 Redis 并没有使用 C 的字符串表示,而是自己构建了一种 简单动态字符串(Simple Dynamic String,SDS)。
SDS结构如下:
struct sdshdr{
unsigned int len; // 记录buf数组中已使用字节的数量
unsigned int free; // 记录 buf 数组中未使用字节的数量
char buf[]; // 字节数组,用于保存字符串
}
SDS 结构图如下:
相比于 C 的原生字符串,Redis 的 SDS 不光可以保存文本数据还可以保存二进制数据,并且获取字符串长度复杂度为 O(1)(C 字符串为 O(N)), 除此之外,Redis 的 SDS API 是安全的,不会造成缓冲区溢出。
SDS相比于C语言中的普通字符串有以下优势和特点:
在Redis中,每个列表都由一个双向链表来实现,该链表的每个节点表示列表中的一个元素。每个节点都包含了指向前一个节点和后一个节点的指针,并且节点中存储了实际的元素值。
双向链表的节点结构如下:
typedef struct listNode {
struct listNode *prev; // 前一个节点指针
struct listNode *next; // 后一个节点指针
void *value; // 节点存储的元素值
} listNode;
而列表本身由一个列表对象(listObject)来包装,其中包含指向链表头节点和尾节点的指针,以及列表的长度(即节点的数量)。
列表对象结构如下:
typedef struct list {
listNode *head; // 链表头节点指针
listNode *tail; // 链表尾节点指针
unsigned long len;// 列表长度(节点数量)
//...
} list;
通过双向链表的结构,Redis的列表数据类型具备了以下特点和优势:
压缩列表(ziplist) 是 Redis 为了节省内存而开发的,是由一系列特殊编码的 连续内存块 组成的顺序型数据结构,一个压缩列表可以包含任意多个节点(entry),每个节点可以保存一个字节数组或者一个整数值。
压缩列表并不是对数据利用某种算法进行压缩,而是将数据按照一定规则编码在一块连续的内存区域,目的是节省内存。
压缩列表的结构如下:
| zlbytes | zltail | zllen | entry1 | entry2 | ... | entryN | zlend |
zlbytes
:表示压缩列表占用的字节数。zltail
:指向压缩列表的尾部元素。zllen
:表示压缩列表中的元素数量。entry1
、entry2
、...、entryN
:压缩列表中的元素,每个元素包含长度字段和实际存储的数据。zlend
:表示压缩列表的末尾压缩列表的每个节点构成如下:
| PrevLen | PrevEntryLength | EntryLength | EntryData |
压缩列表(ziplist)在Redis中具有以下几个优点:
整数集合(intset) 是 Redis 用于保存整数值的集合抽象数据类型,它可以保存类型为 int16_t、int32_t 或者 int64_t 的整数值,并且保证集合中不会出现重复元素。
整数集合底层结构:
typedef struct intset{
uint32_t encoding; // 编码方式
uint32_t length; // 集合包含的元素数量
int8_t contents[]; // 保存元素的数组
}intset;
整数集合的特点如下:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。