您的位置:首页 > 数据库 > Redis

[置顶] REDIS系列之五大对象原理

2017-12-05 16:57 387 查看
Redis并没有采用上文介绍的底层数据结构实现键值对数据库,而是基于底层数据结构实现一套对象系统,包括字符串对象、链表对象、哈希对象、集合对象、排序集合对象。而且,每个对象的底层实现至少存在两种,针对不同的应用场景可以选择不同的实现方式,从而提高效率。

1.对象系统

Redis是
key-value
数据库,每创建一个键值对就会创建两个对象,即一个键对象,一个值对象。Redis中默认键是字符串对象,值是
redisObject
对象。其结构如下:

typedef struct redisObject{

//类型
unsigned int type:4;

//编码
unsigned int encoding:4;

//底层实现数据结构指针
void* ptr;
}


其内存结构如图所示:



其中类型
type
如下:

类型常量对象名称
REDI_STRING字符串对象
REDIS_LIST列表对象
REDIS_HASH哈希对象
REDIS_SET集合对象
REDIS_ZSET有序集合对象
encoding
如下:

编码常量底层数据结构
REDIS_ENCODING_INTlong型整数
REDIS_ENCODING_EMBSTRembstr编码简单动态字符串
REDIS_ENCODING_RAW简单动态字符串
REDIS_ENCODING_HT字典
REDIS_ENCODING_LINKEDLIST双端链表
REDIS_ENCODING_ZIPLIST压缩列表
REDIS_ENCODING_INTSET整数集合
REDIS_ENCODING_SKIPLIST跳跃表和字典
下表表示不同类型和编码的对象:

类型编码对象
REDIS_STRINGREDIS_ENCODING_INT整数值实现字符串对象
REDIS_STRINGREDIS_ENCODING_EMBSTRembstr编码实现简单动态字符串
REDIS_STRINGREDIS_ENCODING_RAW简单动态字符串实现字符串对象
REDIS_LISTREDIS_ENCODING_ZIPLIST压缩列表实现列表对象
REDIS_LISTREDIS_ENCODING_LINKEDLIST双端链表实现列表对象
REDIS_HASHREDIS_ENCODING_ZIPLIST压缩列表实现的哈希对象
REDIS_HASHREDIS_ENCODING_HT字典实现的哈希对象
REDIS_SETREDIS_ENCODING_INTSET整数集合实现的集合对象
REDIS_SETREDIS_ENCODING_HT字典实现的集合对象
REDIS_ZSETREDIS_ENCODING_ZIPLIST压缩列表实现的有序集合对象
REDIS_ZSETREDIS_ENCODING_SKIPLIST跳跃表和字典实现的有序集合对象
从上表可以看出任意一种对象都至少有两种实现方式

OBJECT ENCODING
命令显示对象的编码类型

redis>set msg "hello world"

redis>OBJECT ENCODING msg

"embstr"


2.字符串对象

字符串对象有
int
raw
embstr
三种编码方式,其底层数据结构三个原则:

如果字符串对象保存的是整数值,并且这个整数值可以用long型数据表示,则底层数据采用int型编码

如果字符串对象保存的是一个字符串值,并且这个字符串的长度大于32个字节,那么字符串对象将使用一个简单动态字符串(SDS)保存,即编码方式采用raw.

如果字符串对象保存的是一个字符串值,并且这个字符串的长度小于于32个字节,那么字符串对象将使用embstr字符串保存(连续一块内存),即编码方式采用embstr.

如图是三种编码方式内存结构:



字符串常用命令:

命令功能说明
SET保存字符串值
Get获取字符串值
APPEND追加字符串到末尾
INCRBYFLOAT对浮点数进行加法运算Increase By Float
INCRBY对整数进行加法运算
DECRBY对整数进行减法运算
STRLEN返回字符串长度
SETRANGE将字符串特定索引上单值设置为给定的字符
GETRANGE直接取出并返回字符串指定索引上的字符

3.列表对象

列表对象
ziplist
linkedlist
两种编码方式,其底层数据结构采用编码方式的原则:

列表对象保存的 所有字符串元素的长度都小于64字节时,采用ziplist编码

列表对象保存的元素数量小于512个时,采用ziplist编码

不满足上述条件其他情况,都采用linkedlist编码方式。

其内存结构如下图所示:



列表常用命令如下:

命令功能说明
LPUSH将元素压入列表的表头Left Push
RPUSH将元素压入列表的表位Right Push
LPOP表头元素弹出并删除Left Pop
RPOP表尾元素弹出并删除Right Pop
LINDEX返回指定下标的节点保存的元素List Index
LLEN返回列表的长度List Length
LINSERT插入元素到列表指定位置List Insert
LREM遍历列表,删除包含给定元素的节点L Remove
LTRIM删除压缩列表中不在指定索引范围内的节点
LSET将指定位置的元素保存的值替换为新节点值List Set

4.哈希对象

哈希对象采用
ziplist
hashtable
两种编码方式实现。其底层数据结构采用的编码方式的原则:

哈希对象保存的所有键值对的键和值的字符串长度都小于64字节,采用ziplist编码方式

哈希对象保存的键值对数量小于512个,采用ziplist编码

满足上述两个条件则采用hashtable编码方式

如图是两种编码方式内存结构:



哈希对象常用命令如下:

命令功能说明
HSET将新节点加入到哈希对象Hash Set
HGET在哈希对象中查找指定键对应的值Hash Get
HEXISTS判断指定的键值对是否存在Hash Exists
HDEL将指定的键值对删除Hash Delete
HLEN返回哈希对象中键值对的数量Hash Length
HGETALL返回哈希对象中所有的键和值Hash Get All

5.集合对象

集合对象采用intset、hashtable两种编码方式。其底层数据结构采用的编码方式的原则:

集合对象保存的所有元素都是整数值时,采用intset编码方式;

集合对象保存的元素数量不超过512个时,采用intset编码方式

不满足上述两个条件采用hashtable编码方式

如图是两种编码方式内存结构:



集合对象常用命令如下:

命令功能说明
SADD将所有元素添加到集合里Set Add
SCARD返回集合中包含元素的数量Set Card
SISMEMBER判断给定元素是否在集合中Set Is Member
SRANDMEMBER随机返回集合中一个元素Set Rand Member
SPOP随机返回集合中一个元素,并且删除这个元素Set Pop
SREM删除集合中指定元素Set Remove

6.有序集合对象

有序集合对象采用ziplist或者skiplist编码方式。其底层数据结构编码方式原则:

有序集合保存的元素数量小于128个,有序集合对象采用ziplist编码方式

有序集合对象报读的所有元素成员的长度都小于64字节,采用ziplist编码方式

不满足上述两个条件时,采用skiplist编码方式。

如图是两种编码方式内存结构:



有序集合对象常用命令如下:

命令功能说明
ZADD将新元素加入到有序集合
ZCARD返回有序集合中元素个数
ZCOUNT遍历有序集合统计分值在给定范围内的节点的数量
ZRANGE正序返回给定索引范围内的所有元素
ZREVRANGE逆序返回给定索引范围内的所有元素Z Reverse Range
ZRANK正序遍历集合,返回对应元素在集合中的排名
ZREVRANK逆序遍历集合,返回对应元素在集合中的排名Z Reverse Rank
ZREM删除给定的元素ZRemove
ZSCORE查找给定元素的分值Z Score

总结

本文主要介绍Redis数据库中五大对象底层实现的原理,以及每种对象其底层源码编码方式的使用场景,并简单介绍各个对象常用的命令以及含义。

参考文献 《Redis设计与实现(第二版)》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐