Redis--对象-基本原理

本文主要写了针对对象的类型的简介及底层的基本原理
    Redis主要数据结构,比如简单动态字符串(SDS)、双向链表、字典、压缩列表、整数集合等等。
    Redis并没有直接使用这些数据结构来实现键值对数据库,而是基于这些数据结构创建了一个对象系统,这个系统包含字符串对象、列表对象、哈希对象、集合对象和有序集合对象这五种类型对象,每种对象都用到了至少一种前面所说的数据结构。
    通过这五种不同的类型对象,Redis可以在执行命令之前,根据对象的类型来判断一个对象是否可以执行给定的命令。使用对象的另一个好处是,我们可以针对不同的使用场景,为对象设置多种不同的数据结构实现,从而优化对象在不同场景下的使用效率。
    除此之外,Redis的对象系统还实现了基于引用计数技术的内存回收机制,当程序不再使用某个对象的时候,这个对象所占用的内存就会被释放,另外,Redis还通过引用计数技术实现了对象的共享机制,这一机制可以再适当的条件下,通过让多个数据库键共享同一个对象节约内存。
    最后,Redis的对象带有访问时间记录信息,该信息可以用于计算数据库键的空转时长,在服务器启用了maxmemory功能的情况下,空转时长比较大的那些键可能会优先被服务器删除。
1.1 对象的类型与编码
    Redis使用对象来表示数据库中的键和值,每次当我们在Redis的数据库中创建一个键值对时,我们至少会创建两个对象,一个对象用作键值对的键(键对象),另一个对象用作键值对的值(值对象)。
    举个例子,以下SET命令在数据库中创建了一个新的键值对,其中键值对的键是一个包含了字符串值“msg”对象,而键值对的值则是一个包含了字符串值“helloworld”的对象。
    Redis中的每个对象都是由一个redisObject结构表示,该结构中和保存数据有关的三个属性分别是type属性、encoding属性和ptr属性:

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

1.1.1  类型
    对象的type属性记录了对象的类型,这个属性的值可以是表8-1列出的常量的其中一个。
在这里插入图片描述
    对于Redis数据库保存的键值对来说,键总是一个字符串对象,而值则可以是字符串对象、列表对象、哈希对象、集合对象或者有序集合对象的其中一种,因此:
    1.当我们称呼一个数据库键为“字符串键”时,我们指的是“这个数据库键所对应的值为字符串对象”;
    2.当我们称呼一个键为“列表建”时,我们指的是“这个数据库键所对应的值为列表对象”。
    TYPE命令的实现方式也与此类似,当我们对一个数据库键执行TYPE命令时,命令返回的结果为数据库键对应的值对象的类型,而不是键对象的类型:

#键为字符串对象,值为字符串对象
redis> SET msg "hello world"
ok
redis> TYPE msg
string

#键为字符串对象,值为列表对象
redis>RPUSH numbers 1 3 5
(integer)6
redis> TYPE numbers
list

#键为字符串对象,值为哈希对象
redis> HMSET profile name tom age 25 career Programmer
ok
redis> TYPE profile
hash

#键为字符串对象,值为集合对象
redis>SADD fruits apple banana cherry
(integer) 3
redis> TYPE fruits
set

#键为字符串对象,值为有序集合对象
redis>ZADD price 8.5 apple 5.0 bababa 6.0 cherry
(integer) 3
redis> TYPE price
zset

    表8-2列出了TYPE命令在面对不同类型的值对象是产生的输出。
在这里插入图片描述
1.1.2 编码和底层实现
    对象的ptr指针指向对象的底层实现数据结构,而这些数据结构由对象的encoding属性决定。
    encoding属性记录了对象所使用的的编码,也即是说这个对象使用了什么数据结构作为对象的底层实现,这个属性的值可以是表8-3列出的常量的其中一个。
在这里插入图片描述
    每种类型的对象都至少使用了两种不用的编码,表8-4列出了每种类型的对象可以使用的编码。
在这里插入图片描述
    使用OBJECT ENCODING命令可以查看一个数据库键的值对象的编码:

redis>SET msg "hello world"
OK

redis> OBJECT ENCODING msg
"embstr"

redis>SET story "long long long long long ago "
on
redis> OBJECT ENCODING story
"raw"

redis> SADD numbers 1 3 5 
(integer) 3

redis> OBJECT ENCODING numbers
"intset"

redis> SADD numbers "seven"
(integer) 1

redis> OBJECT ENCODING numbers
"hashtable"

    表8-5列出了不同编码的对象所对应的OBJECTENCODING命令输出。
在这里插入图片描述
在这里插入图片描述
    通过encoding属性来设定对象所使用的编码,而不是为特定类型的对象关联一种固定的编码,极大的提升了Redis的灵活性和效率,因为Redis可以根据不同的使用场景来为一个对象设置不同编码,从而优化对象在某一场景下的效率。
    举个例子,在列表对象包含的元素较少时,Redis使用压缩列表作为列表对象的底层实现:
    1. 因为压缩列表比双端链表更节约内存,并且在元素数量比较少时,在内存中以连续块方式保存的压缩列表比起双端链表可以更快被载入到缓存中。
    2. 随着列表对象包含的元素越老越多,使用压缩列表来保存元素的优势逐渐消失时,对象就会将底层实现从压缩列表转向功能更强,也更适合保存大量元素的双端链表上面;
    其他类型的对象也会通过使用多种不同的编码来进行类似的优化。

关于Redis对象的基本一些原理就暂时写到这,具体的五种对象将在别的文章内进行分享

本文由作者摘自《Redis设计与实现》,纯属由于个人想进行记录的习惯,不会作为商业用途传播

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值