Redis基础数据类型
1 SDS
1.1 结构体
以下结构体表示一个SDS值:
1 |
|
1.2 结构图
1.3与c字符串的区别
可以常数复杂度获取字符串长度
c中获取字符串长度的方式是通过线性遍历,而SDS由于存储已使用的字节数量,可以通过常数复杂度获取
杜绝缓冲区溢出
例如,c的字符串在使用
strcat
为原字符串添加字符串时,如果未分配有效空间,很可能造成缓冲区溢出。而SDS的API会检查空间是否满足修改所需的要求。减少修改字符串时带来的内存重分配次数
c中字符串在执行拼接操作时,如果空间不足,需要通过内存重分配来扩张空间大小,如果忘了则会发生
缓冲区溢出
如果执行截断操作,程序就要释放不再使用的空间,如果忘了则会发生
内存泄漏
以上两种操作,如果频繁地发生,是会对性能造成影响的。
由此,SDS通过空间预分配和惰性空间释放两种策略来进行优化
空间预分配
当SDS在分配空间时,如果SDS长度小于
1M
,则会分配原来长度len同样大小的未使用空间(还得+1,空字符);如果SDS大于1M
,则会分配1M未使用空间+1。这样使得内存分配次数从N次降低到最多N次惰性空间释放
当SDS在释放空间时,不会进行空间回收,而是使用
free
属性将字节数量记录下来,方便将来使用
二进制安全
由于c中不能包含空字符(会被当成结尾),限制了不能保存像图片,音频,视频这样的二进制数据。但SDS由于通过len来判断字符串是否结束,从而不会发生这种问题。
兼容部分C字符串函数
2 链表
2.1 结构体
1 |
|
1 |
|
2.2 结构图
3 字典
字典底层使用哈希表,一个哈希表可以有多个哈希表节点,每个哈希表节点就保存了字典中的一个键值对
3.1 结构体
1 |
|
1 |
|
1 |
|
3.2 结构图
4 跳跃表
一种有序数据结构,通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。
支持平均O(logN),最坏O(N)复杂度的节点查找
4.1 结构体
1 |
|
1 |
|
4.2 结构图
5 整数集合
用于保存整数值的集合抽象数据结构,可以保存类型为int16_t、int32_t或者int64_t的整数值,并且保证集合中不会出现重复元素。
5.1 结构体
1 |
|
5.2 结构图
6 压缩列表
6.1 构成
- 列表
节点
previous_entry_length
记录了压缩列表中前一个节点的长度。
encoding
记录了节点的content属性所保存数据的类型以及长度
content
保存节点的值,节点值可以是一个字节数组或者整数
7 对象
Redis并没有直接使用上述数据结构来实现键值对数据库,而是基于这些数据结构创建了一个对象系统,这个系统包含字符串对象、列表对象、哈希对象、集合对象和有序集合对象这五种类型的对象。
7.1 结构体
1 |
|
7.2 字符串对象
7.3 列表对象
列表对象的编码可以是ziplist
或者linkedlist
。
ziplist
linkedlist
运用场景
比如twitter的关注列表、粉丝列表等都可以用Redis的list结构来实现,再比如有的应用使用Redis的list类型实现一个简单的轻量级消息队列,生产者push,消费者pop/bpop。
7.4 哈希对象
哈希对象的编码可以是ziplist
或者hashtable
。
ziplist
hashtable
运用场景
假设有多个用户及对应的用户信息,可以用来存储以用户ID为key,将用户信息序列化为比如json格式做为value进行保存。
7.5 集合对象
集合对象的编码可以是intset
或者hashtable
。
intest
hashtabl
运用场景
在微博应用中,每个用户关注的人存在一个集合中,就很容易实现求两个人的共同好友功能。
7.6 有序集合对象
有序集合的编码可以是ziplist或者skiplist。
ziplist
skiplist
运用场景
比如用户的积分排行榜需求就可以通过有序集合实现。也可以通过Sorted Set实现有优先级或按权重的队列。