1.动态字符串
redis中使用c语言的字符床存储字面量,默认字符串存储采用自己构建的简单动态字符串SDS(symple dynamic string)
redis包含字符串的键值对都是用SDS实现的
结构s d s.h/sdshdr
struct sdshdr{
int len; //buf使用的长度 SDS的长度
int free; //buf未使用的长度
char buf[]; //字节数据,保持字符串
}
free属性值 0,表示SDS没有分配使用空间
len属性值 5 表示SDS保存了5个字节长度的字符串
buf属性值char类型的数组,最欠扁保存 R e d i s五个字符,最后 \0 空字符结束
SDS和原生的c字符串的区别
获取字符串长度的时间复杂度O(1),c字符串O(N)
没有缓冲区溢出,c字符串在长度超过开辟的内存空间就会造成缓冲区溢出,SDS在修改时会查看当前长度和空间是否足够
减少内存重新分配次数。SDS在增加和减少字符串长度时候不会重新分配内存,也不会内存泄漏
空间预分配。SDS扩展空间 len<1mb 会预分配len大小的空间, len>1mb会预分配1mb空间
惰性空间释放 缩减字符串长度空间不会释放,会放到free属性记录
二进制安全 c字符串只能结尾空字符串,所以只能存储文本,SDS可以存储图片 音频 压缩文件等二进制数据,不会对二进制数据进行过滤限制等
2.链表。最常见的数据结构,c语言没有内置这种结构 redis构建了自己的链表实现
结构a d li s t.h/listNode
typedef struct listNode{
struct listNode *prev;
struct listNode *next;
void *value;
}listNode
typedef struct list{
listNode *head;
listNode *tail;
unsigned long len;
void *(*dup) (void *ptr);
void (*free) (void *ptr);
void (*match) (void *ptr, void *key);
}
redis实现了双端链表(prev next指针) 无环(头节点prev和尾节点的next指向null)。带头指针和尾指针 带长度值 多态
3.字典 符号表 关联数组 映射 一种key-value的抽象数据结构
redis的字典是有的hash表定义 dict.h/dictht
typedef struct ditch{
dictEntry **table;
unsigned long size;
unsigned long size mask;
unsigned long used;
}ditch;
typedef struct dicEntry{
void *key;
union{
void *val;
uint64_tu64;
int64_ts64;
}v;
struct dictEntry *next;
}dicEntry;
next属性值用来解决hash冲突的 链式地址法
4.跳跃表 有序的数据结构 每个节点存在多个指针,可以快速访问其他节点
结构
typedef struct zskiplistNode{
struct zskiplistlevel{
struct zskiplistNode *forward;
unsigned int span;
}
struct zskiplistNode *backward;
double score;
robj *obj;
}
5.整数集合 只包含整数值元素。元素数量不多的集合 redis会使用整数集合作为集合键的底层实现
保存 int16 32 64_t 类型的整数值 集合元素不重复
typedef struct inset{
uint32_t encoding;
uint32_t length;
int8_t contents[];
}iniset;
contents 数组元素不重复 从小到大排列
6.压缩列表 为了节约内存而开发的,特殊编码的连续内存快组成的顺序型数据结构