我们常说的redis的数据类型实际上指的是redis对象 .
redis并没有直接使用前面介绍的数据结构来作为我们常说的字符串,list,set,sortset,map.
而是针对不同的情况,对同一个Redis对象采取多种数据结构类型.
对象结构体定义
typedef struct redisObject {
unsigned int type;
unsigned int encoding;
void * prt;//指向底层具体的数据结构地址
unsigned int refcount;//引用数量
unsigned lru:22//最后一次访问时间
}
lru用于在设置了最大的maxmemory情况下,优先剔除那些长时间未访问的对象.
使用object idletime key 来查看对象已经多次时间未访问了.
type
指明对象的类型。
- redis_string
- redis_list
- redis_set
- redis_zset
- redis_hash
使用type key可以查询出指定对象的类型
其中string 对象是唯一一个可以在其他对象中使用的类型,例如list对象ptr指向的指针类型就是string。因为其能存int ,string 以及byte数组
encoding
指明对象的底层数据结构。
| 类型 | 对应的数据结构 |
|---|---|
| redis_encoding_int | 结构中的ptr直接强转为long |
| redis_encoding_enmstr | embstr编码的sds |
| redis_encoding_raw | sds |
| redis_encoding_ht | dict |
| redis_encoding_linkedlist | linklist |
| redis_encoding_skiplist | skiplist |
| redis_encoding_ziplist | ziplist |
| redis_encoding_intset | intset |
查询对象的encoding: object encoding key
1. redis_string的底层数据结构
-
redis_encoding_int:例如
set k 123456,底层的encoding为该值 -
redis_encoding_embstr:字符串长度小于
32个字节时,使用enmstr,本质上和redis_encoding_raw一样,只是redis_encoding_raw会调用两次内存分配函数,一次为创建redisObject,一次为sds.而redis_encoding_embstr只分配一次连续的内存空间给两个对象使用(不知道咋实现的),并且释放的时候也释放一次. -
redis_encoding_raw:当存储的字符串长度大于
32个字节时,使用raw
redis是使用字符串来保存long double的
2. redis_list的底层数据结构
-
redis_encoding_ziplist内容保存到
ziplist_entry中 -
redis_encoding_linkedlist保存的节点值是
redisObject_string
当节点元素数量(512个)和节点内容大小(64字节)都小于括号内的值时,采用ziplist,否则升级为linkedlist.该值可修改.
3. redis_set的底层数据结构
redis_encoding_intsetredis_encoding_ht
4. redis_zset的底层数据结构
redis_encoding_ziplistredis_encoding_skiplist 和 redis_encoding_ht
5. redis_hash的底层数据结构
-
redis_encoding_ziplist存入时,先将
key压入ziplist的尾部,然后把value压入ziplist.key和value都是一对存放的.查询的时候,遍历即可.
问题是重复
key如何处理? 查找覆盖。 -
redis_encoding_htkey和value都是redisObject_string元素大小和数量的限制和
redis_linkedlist相同.都是64byte和512个元素
对象共享
Redis会在初始化服务器时,创建一万个字符串对象,这些对象包含了从0到9999的所有整数值,当服务器需要用到值为0到9999的字符串对象时,服务器就会使用这些共享对象,而不是新创建对象
对象共享只针对于0-9999的整数字符串.因为判断Redis对象相等的代价是就结构约复杂,越难判断.
使用object refcount key来查看引用次数
问题
redis存储一个数字字符串,为什么底层显示的是int,而不是字符串?