String底层
String的底层并不是简单的C字符串简单动态字符串(Simple Dynamic String,SDS),详细讲解可以参考惊呆了!Redis中的字符串竟然不是C字符串!!!
List底层
List的底层实现是压缩列表(ziplist)和链表(双向链表linkedlist)
当列表键(是指列表的value底层实现)包含的列表项比较少的时候,就用压缩列表来做列表的底层实现
压缩列表实现
zlbytes
占4字节,记录压缩列表占用的内存字节
zltail
占4字节,记录压缩列表尾到表头距离的字节
zllen
占2字节,记录压缩列表包含的节点数
entryx
占2字节,压缩列表的各个节点(可以是字节数组和整数值)
zlend
占1字节,标记压缩列表的表尾
链表实现
下面给出每一个节点的底层实现
typedef struct listNode {
struct listNode *prev;
struct ListNode *next;
void *value;// 保存节点的值
}listNode;
而list的底层就是多个链表节点连在一起的,另外,list还提供了一些固有的属性,方便操作,下面给出list的简单底层实现
typedef struct list {
listNode *head;// 该指针指向链表的表头
listNode *tail;// 该指针指向链表的表尾
unsigned long len;// 记录链表的长度
void *(*dup) (void *ptr);
void (*free) (void *ptr);
void (*match) (void *ptr,void *key);
}list;
list在操作链表的表头表尾和长度时,时间复杂度是O(1),list中还封装了有dup、free和match函数,分别用于复制链表节点所保存的值,释放链表节点所保存的值,对比链表节点所保存的值和另一个输入值是否相等。
列表常用操作
lpush
从列表的左侧添加元素
rpush
从列表的右侧添加元素
lpop
从列表的左侧弹出一个元素,并返回该元素的值
rpop
从列表的右侧弹出一个元素,并返回该元素的值
lindex
返回指定索引的值
llen
返回列表的长度
lrem
删除包含给定元素的节点
Hash底层
Hash的底层是ziplist和hashtable,上面已经说了压缩列表,这里着重讲解HashTable。
压缩列表
当数据少的时候用压缩列表,存储的时候是成对(键值对)存储的。
HashTable
哈希表里保存了一个hash表数组、hash表的大小、hash表大小掩码,用于计算索引值、hash表的节点数
type struct dictht {
dictEntry **table;
unsigned long size;
unsigned long sizemask;
unsigned long used;
}dictht;
table是一个hash表数组,该数组里的每个元素都保存着一个指针,保存键值对。 当同一个key对应多个键时,通过链地址法解决冲突(详情可以看面试官问你什么是Hash表),当数据多的时候,用跳跃表来实现,跳跃表基本可以和红黑树相媲美。
Hash常用操作
hsest
添加新节点
hget
返回节点的值
hexists
查找指定键
hdel
删除指定键
hlen
返回键值对数
hgetall
返回所有键和值
Set底层
底层是整数集合(intset)和hashtable
整数集合
typedef struct intset {
uint32_t encoding;
uint32_t length;
int8_t contents[];// 这里保存的int类型,会根据存储数据而改变,可能是int_8、int_16、int_32等
}intset;
其底层是一个数组,该数组中的元素不可重复。
Set常用操作
sadd
添加新元素到集合
scard
返回集合中的元素个数
sismember
查找指定元素
smembers
返回集合元素
srandmember
随机返回一个键
spop
随机取出一个键返回,并删除
srem
删除指定键
Zset底层
底层是ziplisst和skiplist,即是压缩列表和跳跃表
zset的特点就是可以通过分值排序。
Zset常用操作
zadd
插入成员和分值
zcard
获取元素数量
zcount
统计分值在范围内的元素数
zrange
从头遍历,返回给定索引范围内的元素
zrevrange
从尾遍历,返回给定索引范围内的元素
zrank
从头遍历,返回给定元素的排名
zrevrank
从尾遍历返回给定元素的排名
zrem
删除所有给定元素的节点以及分值节点
zscore
获取给定元素的分值