Redis底层数据结构


redisObject

大家都知道我们在使用redis的时候有五种数据类型可以使用分别是string,list,hash,set,sorted_set,但是这五种数据可以看成是已经封装好的数据结构,就像Java里面的ArrayList,我们使用的是ArrayList但是它底层使用的数据结构还是数组.所以我们现在需要了解的就是redis中我们使用的五种数据类型底层是什么数据结构.

首先我们需要知道的是,redis中所有的对象都是用一个同一个对象来表示的,这个对象就是**redisObject**,它的定义如下

typedef struct redisObject{
   
     //类型,
     unsigned type:4;
     //编码
     unsigned encoding:4;
     //指向底层数据结构的指针
     void *ptr;
     //引用计数,该属性与数据无关
     int refcount;
     //记录最后一次被程序访问的时间,该属性与数据无关
     unsigned lru:22;
 
}robj

1.type属性

type字段记录了当前对象的类型,就是我们说的那五种类型string,list,hash,set,sorted_set.其实大家要是对redis的命令比较了解的话,就知道有一个type命令
在这里插入图片描述

其实这个type命令就是获取当前redisObject的type属性

2.encoding 和 ptr 属性

ptr就是指针,指向该对象的底层实现.

encoding属性表明就是我们这片文章要讲的底层数据类型,类型如下

在这里插入图片描述

其实大家对动态字符串,双端(向)链表等可能已经比较了解了,但是对压缩列表(ziplist)等可能不是很了解.为了证明这些底层数据结构的存在我们可以实际的使用redis来试一下.使用OBJECT ENCODING key命令就可以找到对应对象的底层实现

在这里插入图片描述

大家可以看到,我是使用了string这种类型,设置了3个键值对,然后调用OBJECT ENCODING key命令分别查看底层实现,发现都不同,而且这三种在我们上面的表中都出现了.

这说明了一种类型的数据结构底层实现可以有多种.

下面我们就来看看,每种类型分别有哪些不同的实现方式
在这里插入图片描述

3.对使用多种数据结构的思考

可以看到,redis中每种数据类型都有不同底层实现,那么为什么要大费周章的这样做呢? 简单一点不好吗?

在我看来,这是由于redis的特殊性造成的,redis是内存数据库,所有的数据都存放在内存中,而内存作为一种十分十分珍贵的计算机资源,我们必须好好的利用它,使得它尽可能多的存储数据

(一)string的底层实现

有上面的图我们可以看到,string有三种具体的是实现方式分别是int,embstr,raw

1.int–使用整数值实现的字符串对象

还记得我们的string可以实现计数器的功能吗,这就是因为当我们对一个string类型的数据设置的值为数字的时候Redis就使用int这种类型来作为它的底层实现,但是我们还是有一点小小的细节需要注意

  1. 虽然这种类型叫做int,但是它底层是用C语言的long来表示的.
  2. 正是因为使用long来存,所以int类型表示的数值大小是有限制的,当超过了范围,就会自动转成raw或者是embstr

下面我们验证一下是否如此(需要注意的是 int 的最大值为 2147483647,long的最大值为 9223372036854775807)

验证第一条规则: 可以看到,我们设置的数值超过了int的最大值(64位机器下),但是结果依然是int

在这里插入图片描述

验证第二条规则:我们先设置了long的最大值,发现结果不变,但是我们+1,超过了边界值,就变成了embstr

在这里插入图片描述

2.sds-动态字符串

string底层还有两种实现,不过他们都是基于**sds(simple dynamic string)**来实现的.所以先来了解一下sds.

1.Redis中的SDS简介

C语言中没有string,但是Redis也没有使用C语言中原生的char数组,而是在此基础上自己构建了一种Simple Dynamic String SDS来表示string.

2.SDS的优越性

上面讲了redis中的string使用的是SDS,那么为什么要构建一种新的SDS来表示String,而不是使用char数组呢?

其实这是为了解决char数组中的一些痛点.那么SDS解决了哪些痛点呢?

  1. SDS获取string长度的时间复杂度是 O(1),而char数组是 O(N)
  2. SDS不会造成缓存区溢出问题.
  3. SDS不仅能保存文本数据,而且可以保存二进制数据
3.SDS底层实现
/* Note: sdshdr5 is never used, we just access the flags byte directly.
 * However is here to document the layout of type 5 SDS strings. */
// 注意:sdshdr5从没没有被使用过
struct __attribute__ ((__packed__
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值