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五个字符,最后 空字符结束
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.压缩列表 为了节约内存而开发的,特殊编码的连续内存快组成的顺序型数据结构