redis基本数据结构与对象

一:简单动态字符串(SDS)

1.结构

struct sdshdr{
	//当前字符串的长度
	int len;
	//可以分配的空间
	int free;
	//字符数组
	char buf[];
}

2.应用场景

  • 用于保存redis中键,当值值list,set,string等等时,其里面包含的值也为SDS
  • 用于缓冲区,AOF缓冲区和客户端输入缓存区

3.特性及优点

  • 可以使用常数的时间复杂度获取字符串长度
  • 避免缓冲区溢出,sdscat(拼接字符串的API),可以在拼接字符串的时候检查空间是否足够
  • 空间预分配,在一个SDS小于1MB时,会多分配一倍+1的空间(多的1用于保存空字符串)在大于等于1MB时会多分配1MB+1的空间
  • 惰性空间释放,字符串长度变短时,会保留多余的空间,避免内存重新分配
  • 二进制保存,相比于C语言中字符串(必须符合编码方式,比如ASCII),C语言中字符串不能保存空字符串,
    决定了不能保存图片,音视频等等二进制数据文件而SDS则可解决这个问题
  • 可以兼容C语言,使用<string.h>中函数

二:链表

1.结构

typedef struct listNode{
	//前置节点
	struct listNode *prev;
	//后置节点
	struct listNode *next;
	//节点值
	void *value;
}listNode;

2.应用场景

  • 广泛使用于redis,比如列表的键,发布订阅,慢查询,监视器等等

3.特性及优点

  • 双向无环链表

三:字典

1.结构

哈希表

typedef struct dictht{
	//哈希表数组
	dictEntry **table;
	//哈希表大小
	umsigned long size;
	//哈希表大小掩码,计算索引值,永远等于size-1
	unsigned long sizemask;
	//哈希表已有节点数量
	unsigned long used;
}dictht;

字典

typedef struct dict{
	//类型特定函数
	dictType *type;
	//私有数据
	void *privdata;
	//哈希表
	dictht ht[2];
	//rehash索引,当rehash不在时,值为-1
	int trehashidx;
}

2.应用场景

  • 用于保存redis数据库,保存哈希键等等

3.特性及优点

  • redis中的字典由hash构成,使用MurmurHash算法计算出在hash值,再对hash值计算出索引,最后存放到hash表对应位置
  • redis使用链地址法解决hash冲突
  • 在对hash进行扩容的时候,使用到了ht[1],使用了渐进式的扩容(trehashindex),将hash桶上面数据逐一复制到ht[1],之后释放ht[0],然如果正在rehash的时候,进行增删改查操作,会在ht[0]和ht[1]两个上面都去查找,直至找到了相应数据才操作
  • hash扩容时机,1:没有执行BGSAVE或BGREWRITEAOF,负载因子>=1,2:正在执行BGSAVE或BGREWRITEAOF,负载因子>=5,负载因子=ht[0].used / ht[0].size

四:跳跃表

1.结构

跳跃表节点

typedef struct zskiplistNode{
	//后退指针
	struct zskiplistNode *backward;
	//分值
	double score;
	//成员对象
	robj *obj;
	//层
	struct zskiplistLevel{
		//前进指针
		struct zskiplistNode *forward;
		//跨度
		unsigned int span;
	}level[];
}zskiplistNode;

跳跃表

typedef struct zskiplist{
	//头尾节点
	struct skiplistNode *header,*tail;
	//表中节点数量
	unsigned long length;
	//表中层数最大的节点层数
	int level;
}zskiplist;

2.应用场景

  • 是有续集合的底层实现之一

3.特性及优点

  • redis中跳跃表主要由zskiplist和zskiplistNode组成
  • 节点层高为1~32的随机数
  • 多个节点可包含同样的分值,但成员变量唯一,节点按照分值大小排序,其次按照成员对象大小排序

五:整数集合

1.结构

typedef struct intset{
	//编码方式
	uint32_t encoding;
	//集合包含的元素数量
	uint32_t length;
	//保存元素的数组
	int8_t contents[];
}intset;

2.应用场景

  • 可作为集合键的底层实现

3.特性及优点

  • 底层以数组有序无重复方式保存元素,在新增数据类型超出现在数据类型范围时,会升级,节约了内存,但不支持降级

六:压缩列表

1.结构

压缩列表结构:

zlbyteszltailzllenentry1entry2entryNzlend

zlbytes,4字节,记录整个压缩列表占用内存字节数

zltail,4字节,记录压缩列表表尾节点到起始位置的偏移量

zllen,2字节,记录整个列表包含的节点数量

entry,列表节点

zlend,1字节,列表末尾标记

列表节点结构:

previous_entry_lengthencodingcontent

previous_entry_length,记录压缩列表中前一个节点的长度

encoding,记录节点content保存的数据类型以及长度

content,记录保存节点的值,可以是字节数组或者整数,值的类型和长度由encoding决定

2.应用场景

  • 作为列表键和和哈希键的底层实现之一

3.特性及优点

  • 连锁更新,当列表中新增或者删除节点的时候,就可能引起整个列表的改变,因为每个元素的扩展会对后面的元素产生影响

  • 同样,节约内存

七:对象

1.结构

typedef struct redisObject{
	//类型
    unsigned type:4;
    //编码
    unsigned encoding:4;
    //指向底层实现数据结构的指针
    void &ptr;
    //...
} robj;

2.使用及详解

  • redis中的每个键值对都是一个对象
  • 通常redis在面向客户端提供了string,list,set,zset,hash五种数据结构(指的是值,键都是String),这五种数据结构底层实现分别为
  1. String:int,embstr(字符串),raw(SDS)
  2. list:ziplist(压缩列表),linkedlist(双向链表)
  3. hash:ziplist,ht(字典)
  4. set:intset,ht
  5. zset:ziplist,skiplist(跳表)
  • redis中的对象回收使用了引用计数法,此外,还实现了对象共享机制,从而可实现多个数据库共享一个对象。

  • redis共享值为0-9999的字符串对象

  • 每个对象会记录自己最后一次被访问的时间,用于计算空转时间(当前时间-最后一次访问时间),可用于删除策略

八:常用命令

1.String

set key val
get key
append key val
substr key start end

2.list

rpush key val
lpush key val
llen key
lrange key start end
ltrim key start end
lindex key index
lpop key
rpop key

3.hash

hset key field
hget key field
hmget key fields
hmset key field integer
hlen key
hkeys key
hvals key
hgetall key

4.set

sadd key member
srem key member
srandmember key
spop key
sinter key1 key2 ...
sunion key1 keys
sdiff key1 keys

5.zset

zadd key score member score member ...
zrem key member
zcard key
zcount key min max
zrank key member
zscore key member

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值