REDIS系列之五大对象原理

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.字符串对象

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

  • 如果字符串对象保存的是整数值,并且这个整数值可以用long型数据表示,则底层数据采用int型编码
  • 如果字符串对象保存的是一个字符串值,并且这个字符串的长度大于32个字节,那么字符串对象将使用一个简单动态字符串(SDS)保存,即编码方式采用raw.
  • 如果字符串对象保存的是一个字符串值,并且这个字符串的长度小于于32个字节,那么字符串对象将使用embstr字符串保存(连续一块内存),即编码方式采用embstr.
    如图是三种编码方式内存结构:
    这里写图片描述
    字符串常用命令:
命令功能说明
SET保存字符串值
Get获取字符串值
APPEND追加字符串到末尾
INCRBYFLOAT对浮点数进行加法运算Increase By Float
INCRBY对整数进行加法运算
DECRBY对整数进行减法运算
STRLEN返回字符串长度
SETRANGE将字符串特定索引上单值设置为给定的字符
GETRANGE直接取出并返回字符串指定索引上的字符

3.列表对象

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

  • 列表对象保存的 所有字符串元素的长度都小于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.哈希对象

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

  • 哈希对象保存的所有键值对的键和值的字符串长度都小于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设计与实现(第二版)》

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值