Redis的设计与实现笔记 -- 对象

//一些命令/

LPUSH 将元素推入列表头

RPUSH 将元素推入列表位

LLEN 返回列表长度

/

 

 

Redis中的每个对象由一个redisObject结构表示

typedef struct redisObject{

//类型
unsigned type:4;
//编码
unsigned encoding:4;
//指向底层实现数据结构的指针
void *ptr;

}robj;

字符串对象 

字符串对象的编码可以是:int, raw,embstr

字符串长度大于39字节会用raw编码 embstr编码分配两次内存 p65

127.0.0.1:6379> SET num 10086
OK
127.0.0.1:6379> OBJECT ENCODING num
"int"
127.0.0.1:6379> SET story "long long long ago there lived a king ..."
OK
127.0.0.1:6379> STRLEN story
(integer) 41
127.0.0.1:6379> OBJECT ENCODING story
"raw"

小于39字节会用embstr编码 embstr编码分配一次内存

127.0.0.1:6379> SET story1 "long long ..."
OK
127.0.0.1:6379> STRLEN story1
(integer) 13
127.0.0.1:6379> OBJECT ENCODING story1
"embstr"

注意:long double 类型的浮点数在Redis中也是作为字符串保存的!

127.0.0.1:6379> SET pi 3.14159
OK
127.0.0.1:6379> TYPE pi
string

127.0.0.1:6379> OBJECT ENCODING pi
"embstr"

embstr字符串是只读的,当我们对embstr编码的字符串对象执行任何修改命令时,程序会将对象的编码从embstr转为raw,然后再执行修改命令 

127.0.0.1:6379> GET num
"10086"
127.0.0.1:6379> OBJECT ENCODING num
"int"
127.0.0.1:6379> APPEND num "is a good number"
(integer) 21
127.0.0.1:6379> OBJECT ENCODING num
"raw"

列表对象,哈希对象,集合对象

列表对象

列表对象的编码可以是ziplist(压缩列表作为底层实现)或者linkedlist

127.0.0.1:6379> RPUSH numbers 1 "three" 5
(integer) 3
127.0.0.1:6379> OBJECT ENCODING numbers
"ziplist"

字符串对象是Redis五种类型对象中唯一一种会被其他四种对象嵌套的对象

 

满足以下条件时列表使用ziplist编码:

1)每个元素的字符串长度都小于64Byte

2)元素个数小于512个

不满足以上条件的都使用linkedlist编码

127.0.0.1:6379> RPUSH myList 1 "three" 5
(integer) 3
127.0.0.1:6379> OBJECT ENCODING mylist
"ziplist"

 

127.0.0.1:6379> RPUSH  myList "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"
(integer) 4
127.0.0.1:6379> OBJECT ENCODING myList
"linkedlist"

哈希对象

哈希对象的编码可以是ziplist或者hashtable

 当键值对加入哈希对象时,先将键Push到ziplist表尾,再将值Push到表尾 : 键---值---键---值

有序集合对象

127.0.0.1:6379> HSET myHash name "dxt00"
(integer) 1
127.0.0.1:6379> HSET myHash age 18
(integer) 1
127.0.0.1:6379> HSET myHash career "Programmer"
(integer) 1
127.0.0.1:6379> HGET myHash name
"dxt00"
127.0.0.1:6379> HGET myHash age
"18"
127.0.0.1:6379> HGET myHash career
"Programmer"

满足以下条件时哈希对象使用ziplist编码:

1)所有键值对的键和值的字符串长度都小于64Byte

2)键值对个数小于512个

不满足以上条件的都使用hashtable编码

127.0.0.1:6379> EVAL "for i=1, 512 do redis.call('HSET', KEYS[1], i,i)end" 1 "myHash"
(nil)
127.0.0.1:6379> HLEN myHash
(integer) 515
127.0.0.1:6379> OBJECT ENCODING myHash
"hashtable"

集合对象

集合对象编码可以是inset或者hashtable

只有集合元素全是整数时,才用intset编码

127.0.0.1:6379> SADD mySET 1 3 5
(integer) 3
127.0.0.1:6379> OBJECT ENCODING mySET
"intset"
127.0.0.1:6379> SADD mySET "seven"
(integer) 1
127.0.0.1:6379> OBJECT ENCODING mySET
"hashtable"

有序集合对象

有序集合对象编码可以是ziplist或者skiplist

一个集合元素包含:member和score

每个集合元素使用两个紧挨着的ziplist节点保存,分别保存元素的成员(member)和分数(score)

127.0.0.1:6379> ZADD myZSET 8.5 apple 3.0 banana 7.0 cherry
(integer) 3
127.0.0.1:6379> OBJECT ENCODING myZSET
"ziplist"

skiplist

typedef struct zset
{
	zskiplist *zsl;
	dict *dict;
};

zsl跳表

按分值从小到大保存了所有集合元素。每个跳表节点是一个集合元素,跳表节点的object属性保存了元素成员(member),  跳表的score属性保存了元素的分值。

dict 为成员到分值的映射

 

///ZSET命令// p81

ZRANK  返回元素成员在跳表的排名

ZRANGE 从表头到表尾遍历跳表,返回给的索引内的所有元素

 

有序集合元素少于128个

元素成员长度都小于64Byte时 用ziplist

否则用skiplist

127.0.0.1:6379> EVAL "for i=1,128 do redis.call('ZADD',KEYS[1],i,i) end" 1 myZSET
(nil)
127.0.0.1:6379> ZCARD myZSET
(integer) 131
127.0.0.1:6379> OBJECT ENCODING myZSET
"skiplist"

对象的空转时长 p87

redisObject除了 type,encoding,ptr,refcount四个属性以外

还包含一个lru属性-->记录了对象最后一次被命令程序访问的时间

 

typedef struct redisObject
{
	usingned lru:22;
}robj;

空转时长:IdleTime = 当前时间- lru

127.0.0.1:6379> SET msg "hello"
OK
127.0.0.1:6379> OBJECT IDLETIME msg
(integer) 12
127.0.0.1:6379> OBJECT IDLETIME msg
(integer) 15
127.0.0.1:6379> OBJECT IDLETIME msg
(integer) 17

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值