Redis的数据结构

什么是redis?
redis是一个单线程,高性能的nosql内存数据库。
Redis拥有以下五种数据类型:

  • String(字符类型)

  • Hash(散列类型)

  • List(列表类型)

  • Set(集合类型)

  • SortedSet(有序集合类型,简称zset)

1.String(字符类型)
底层采用的是数组实现,Redis没有采用c语言的数组,而是自己实现一种名为简单动态字符的抽象类型(simple dynamis string,SDS),如下:

struct sdshdr {
	int len,//记录buf数组中已使用的字节数量,等于SDS所保存的字符串长度
	int free,//记录buf数组中未使用字节的长度
	char buf[];//字节数组,用于保存字符串
};

Redis为什么还要自己定义,不直接使用c语言的数组呢?
①可以直接获取字符串长度(0(1)),c字符串需遍历
②杜绝缓存区溢出(SDS api 会先检查空间,不够会扩容)
③减少修改字符串时带来的内存重分配次数(c字符串长度变化时都需要进行内次重分配,上面的free可以记录空余长度)
④二进制安全(c只能保持字符串,而Redis数组保存的是二进制数据)

常用命令:set get incr incrby decr decrby setnx
利用redis的incr,可以实现分布式环境下的全局唯一ID
2.List(列表类型)
Redis底层是通过双端链表来实现的List(可以实现消息队列),每个链表节点为listNode,多个节点连起来就是List,结构如下:

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

struct list{
	listNode *head;//表头节点
	listNode *tail;//表尾节点
	unsigned long len;//节点数量
}

主要特性如下:
双端:链表节点都有prev和next
无环:表头节点的prev和表尾节点的next都执行null
长度计数:有记录节点长度,方便获取
多态:链表可以保存各种不同类型的值
常用命令:lpush lpop rpush rpop lrange
3.hash类型
hash类型是一种用于保存键值对的抽象数据结构(结构类似于Map<String,Map<String,Object>>)。在Redis里称为字典。
这里的实现类似于Java中的HashMap,数组加链表实现,结构如下:

struct dictht{
	dictEntry **table;//哈希数组
	unsigned long size;//哈希表大小
	unsigned long sizemask;//哈希表掩码,用于计算索引值(等于size-1)
	unsigned long used;//已有节点数量
}
//下面看看dictEntry结构
struct dictEntry{
	void *key;//键
	union{
		void *val;//值
		uint64_t u64;
		int64_t s64;
	}
	dictEntry *next;//如果有hash碰撞,会形成链表,指向单向链表下一个节点(将新节点添加到链表的表头位置)
}

Redis在对哈希表进行扩容或者收缩时,会有rehash,这个过程是渐进式完成的。
常用命令:hset hget hdel hmget hmset
4.zset(有序集合)
Redis底层采用跳跃表实现(按照score排序),结构如下:

struct zskiplistNode{
	struct zskiplistNode *backward;//后退指针
	double score;  //分值   (分值一样时,将按照成员对象的大小来排序)
	robj *obj;  //成员对象
	struct zskiplistLevel{ //层
		struct zskiplistNode *forward;//前进指针
		unsigned int span; //跨度
	}
}

常用命令:zadd zrem zrange zscore
5.set(集合)
底层实现就是采用的是hash类型的key来保证数据不重复(key相同时,后面的覆盖前面的)
常用命令:sadd,srem,smembers
6.其它类型
Redis为了优化性能,底层还有一些其它的数据结构,比如集合里只包含整数类型,采用的就是intset,结构如下:

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

其它:
当一个列表键只包含少量列表项,并且每个列表项要么是小整数,要么就是比较短的字符串,采用的事压缩列表(ziplist);

总结:Redis的数据结构都比较简单,这也是它高性能的一个原因。

参考:<<Redis的设计与实现>>

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值