RedisObject
redis是Key-Value结构,Key是String类型,Value有常见5种数据类型,Value的结构是RedisObject,
typedef struct redisObject {
//类型,占4位,五种对象类型(REDIS_STRING,REDIS_LIST,REDIS_HASH,REDIS_SET,REDIS_ZSET)
unsigned type:4;
//编码,占4位,10种编码
unsigned encoding:4;
//指针,指向底层实现数据结构
void *ptr;
//引用计数,整型,记录对象被引用次数,主要用于对象引用计数和内存回收。
int refcount;
//24位,对象最后一次被访问时间
unsigned lru:LRU_BITS;
}robj;
查看对象类型:type key
127.0.0.1:16379> type myset
set
127.0.0.1:16379>
查看对象编码方式:object encoding key
type都是string,编码方式不同
127.0.0.1:16379> set qu 11
OK
127.0.0.1:16379> object encoding qu
"int"
127.0.0.1:16379> set qu2 aaaa
OK
127.0.0.1:16379> object encoding qu2
"embstr"
127.0.0.1:16379>
SDS
字符串底层对象是SDS(Simple Dynamic String),存储字符串和整型数据。
redis底层是C语言,
C语言中字符串是字符数组以"\0"结尾。
struct sdshdr{
//记录buf数组中已使用字节数量
int len;
//记录buf数组中未使用字节数量
int free;
//字节数组,保存字符串
char buf[];
}
SDS优势:
1.获取字符串长度:SDS是O(1),C是O(n);
2.杜绝缓冲区溢出;
3.减少修改字符串长度时重新分配内存次数;
4.可以存二进制数据,以len属性值而不是空字符串判断是否结束。
字典
字典dict又称散列表(hash),用来存储键值对的一种数据结构。
应用:redis数据库就是使用字典作为底层实现的;哈西键的底层实现之一。
redis字典的实现主要包括:字典(dict),Hash表(dictht),Hash表节点(dictEntry)。
哈希表
typedef struct dictht{
//哈希表数组
dictEntry **table;
//哈希表大小
unsigned long size;
//哈希表大小掩码,用于计算索引值,值总是size-1
unsigned long sizemask;
//该哈希表已有节点数量
unsigned long used;
} dictht
1.Hash表数组初始容量为4,扩容是2倍,8,16等。
2.索引值=Hash值&掩码值(Hash值与Hash表容量取余)
哈希表节点
typedef struct dictEntry{
//键
void **key;
//值
union{
void *val;
uint64_tu64;
int64_ts64
}v;
//指向下个哈希表节点,形成链表,用于解决hash冲突
struct dictEntry *next;
} dictEntry
键值对的值可以是一个指针,也可以是uint64_t或者int64_t的整数,next属性是执行另一个hash节点的指针。
字典
typedef struct dict{
//该字典对应的特定操作函数
dictTyep *type;
//上述函数对应的参数
void *privdata;
//哈希表,两个,
dictht ht[2];
//rehash索引,记录rehash进度,未进行时值为-1
int rehashindex;
}dict
跳跃表
整数集合
整数集合intset是集合键底层实现之一,当一个集合只包含整数值元素,并且元素数量不多时,使用整数集合。
整数集合是一个有序的,存储整数的连续存储结构。可保存int16_t,int32_t,int64_t的整数值,并且不会重复。
typedef struct intset{
//编码方式
uint32_t encoding;
//集合包含元素数量
uint32_t length;
//保存元素数组,类型取决于encoding值
int8_t contents[];
}intset;
当contens数组中有三个int16_t的值,添加一个int64_t的值,数组升级,全部元素都会转为int64_t类型。
整数集合不支持降级,一旦升级,即使int64_t元素被移出数组,编码也不会变。