redis数据库数据类型和底层类型


redis类型 
String字符串        Int 简单动态字符串 sds      

Redis的string自己构建了简单动态字符串,sds

Sds内部又可以转为int,embstr,raw

set a 1
type a
object encoding a
set b acd
type b
object encoding b

 

embstr 和 raw不同在于

embstr分配了一块连续内存存储 raw则没有

所以embstr请求一次内存就能得到 raw需要请求2次内存

 SDS设计的好处:

struct sdshdr{
    unsigned int len; //buf中已经使用的长度
    unsigned int free;//buf中未使用的长度
    char buf[];//柔性数据buf
};

效率 sds单独存储len长度,不会像c通过遍历字符串获取

防止数据溢出 c是没有字符串长度的,相邻的两个字符串的存储有可能是紧挨着的,当一个字符串变长时就没有办法放下,只能侵占后一个字符串的空间。前一个字符串的改变会影响后面字符串的改变。sds设计会先判断len是否满足,不满足会先扩展在进行修改

空间预分配 不仅分配必要的空间还好分配额外的空间,下次修改时会先判断未使用的空间是否够用,满足直接添加,不满足再进行扩充。可以减少内存分配的次数【额外分配未使用空间原则,当字符串修改后len的值小于1M会分配同样大小的未使用空间,如果大于1M会分配1M空间】

惰性空间释放 当字符串缩短后,并不会立即回收空间,而是放在预分配空间中。减少数据内存分配次数

后期因为小字符串会浪费内存,从而进行了改善,通过字符串长度进行sdshdr5,sdshdr8,sdshdr16,sdshdr32类型选择。sds.h文件中 sds.c文件

sdshdr5 很少使用,无法扩容

sdshdr8 正常使用


Hash哈希        Ziplist hashtable

Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。

Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。

Redis的hash的底层是一个dict,当数据量比较小或者数据值比较小时采用Ziplist(界限可以通过config中的值进行修改)

设置一个hash表,hgetall获取在哈希表中指定 key 的所有字段和值

因为时ziplist压缩列表所以出来的值是顺序的

当一个值太大时,底层存储类型变成hashtable,hashtable是无序的,所以获取出来也是无序的

ziplist数据结构:

zlbytes:32位无符号整型,表示整个ziplist所占的空间大小,包含了zlbytes所占的4个字节。这个字段可以再重置整个ziplist大小时不需要遍历整个list来确定大小,空间换时间。

zltail:32位无符号整型,表示整个list中最后一项所在的偏移量,方便再尾部做pop操作

zllen:16位,表示ziplist中所存储的entry数量,也可以看作是长度

entry:不定长,可能又多个

zlend:8位,ziplist的末尾表示,值固定时255

entry的结构:【前一个entry的大小,当前编码类型和长度,真实的字符串和数字】

ziplist

优点:因为是连续的内存空间,所以利用率高,访问效率高

缺点:更新效率低 当插入或删除一个数据的时候,会频繁的扩展或缩小,然后进行数据的搬移。


List列表        Ziplist quicklist 双向循环链表

Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)

一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。

Redis的list有序的数据结构,底层分为ziplist和quicklist

quicklist: 双向循环链表

优点:更新效率高

缺点:增加了内存开销

quicklist 结构,其实是由ziplist组成的双向链表 源码在quicklist.h


Set集合        intset hashtable

Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

集合对象的编码可以是 intset 或者 hashtable。

Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

Redis的set是无序的,自动去重的数据类型,它的底层是一个字典dict。当数据可以用整型并且数据元素小于配置文件中set-max-intset-entries是用intset,否则用dict


Zset有序集合        Ziplist skiplist 跳表

Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。

不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。

有序集合的成员是唯一的,但分数(score)却可以重复。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

Redis的zset是有序的,自动去重的数据类型。底层是由字典dict和跳表skiplist实现的,让数据较少时用ziplist来存储

ziplist可以在配置文件【redis.conf】中通过zset-max-ziplist-entries和zset-max-ziplist-value来配置,使用ziplist

最开始数据量少,选择的压缩列表的数据结构

当所保存的元素超过了zset-max-ziplist-entries对应的值(默认128)转换为跳表;

当添加元素的member的长度大于zset-max-ziplist-value对应的值(默认64)转换为跳表

skiplist跳表 源码server.h文件中

跳表是在列表的技术上增加了多重的索引,来提升查询的效率,以空间换时间,索引是需要占用空间的

通过数据结构的对比,压缩列表在有序性上的性能损耗相对较大,插入数据需要将数据后移;

跳表对数据的插入相对比较友好,可以直接修改指针; 

跳表需要注意多级索引的退化,需要在合适的时机修改或重构索引;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值