ITPub博客

首页 > IT职业 > IT生活 > 《闲扯Redis二》String数据类型之底层解析

《闲扯Redis二》String数据类型之底层解析

IT生活 作者:usli 时间:2021-09-09 10:41:30 0 删除 编辑

一、前言

Redis 提供了5种数据类型:String(字符串)、Hash(哈希)、List(列表)、Set(集合)、Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要。

图片描述

二、疑问与解析

 结构图上显示,String类型有三种实现方式:

  • 使用整数值实现的字符串对象
  • 使用 embstr 编码的动态字符串实现的字符串对象
  • 动态字符串实现的字符串对象

 疑问:embstr 是什么意思,动态字符串又是什么意思?字符串对象到底什么结构?三种实现方式有什么区别呢?

图片描述

不急,咱们一步一步的往下看:

1、Redis中定义的对象的结构体

/*
 * Redis 对象
 */
typedef struct redisObject {
    // 类型 4bits
    unsigned type:4;
    // 编码方式 4bits
    unsigned encoding:4;
    // LRU 时间(相对于 server.lruclock) 24bits
    unsigned lru:22;
    // 引用计数 Redis里面的数据可以通过引用计数进行共享 32bits
    int refcount;
    // 指向对象的值 64-bit
    void *ptr;
} robj;// 16bytes

注释:type表示该对象的类型,即上面 [String,List,Hash,Set,Zset] 中的一个,但为了提高存储效率与程序执行效率,每种对象的底层数据结构实现都可能不止一种,encoding 表示对象底层所使用的编码。

2、Redis对象底层八种数据结构

 REDIS_ENCODING_INT(long 类型的整数)
 REDIS_ENCODING_EMBSTR embstr (编码的简单动态字符串)
 REDIS_ENCODING_RAW (简单动态字符串)
 REDIS_ENCODING_HT (字典)
 REDIS_ENCODING_LINKEDLIST (双端链表)
 REDIS_ENCODING_ZIPLIST (压缩列表)
 REDIS_ENCODING_INTSET (整数集合)
 REDIS_ENCODING_SKIPLIST (跳跃表和字典)

3、embstr与动态字符串

embstr :是专门用于保存短字符串的一种优化编码方式,跟正常的字符编码相比,字符编码会调用两次内存分配函数来分别创建 redisObject 和 sdshdr 结构(动态字符串结构),而 embstr 编码则通过调用一次内存分配函数来分配一块连续的内存空间,空间中包含 redisObject 和 sdshdr(动态字符串)两个结构,两者在同一个内存块中。从 Redis 3.0 版本开始,字符串引入了 embstr 编码方式,长度小于 OBJ_ENCODING_EMBSTR_SIZE_LIMIT(39) 的字符串将以EMBSTR方式存储。

注意: 在Redis 3.2 之后,就不是以 39 为分界线,而是以 44 为分界线,主要与 Redis 中内存分配使用的是 jemalloc 有关。( jemalloc 分配内存的时候是按照 8、16、32、64 作为 chunk 的单位进行分配的。为了保证采用这种编码方式的字符串能被 jemalloc 分配在同一个 chunk 中,该字符串长度不能超过64,故字符串长度限制

OBJ_ENCODING_EMBSTR_SIZE_LIMIT = 64 - sizeof(‘0’)为1 - sizeof(robj) 为16 - sizeof(struct sdshdr)为8 = 39)

动态字符串 :Redis 自己构建的一种名为 简单动态字符串(simple dynamic string,SDS)的抽象类型,并将 SDS 作为 Redis 的默认字符串表示。先简单了解概念,后面看详细解析

4、带着疑问来细品下面一段话

字符串的编码可以是 int,raw 或者 embstr。如果一个字符串内容可转为 long,那么该字符串会被转化为 long 类型,对象 ptr 指向该 long,并且对象类型也用 int 类型表示。普通的字符串有两种 embstr 和 raw。如果字符串对象的长度小于 39 字节,就用 embstr,否则用 raw。

也就是说,Redis 会根据当前值的类型和长度决定使用内部编码实现:恍然大悟

int:8个字节的长整型
embstr:小于等于39个字节的字符串
raw:大于39个字节的字符串

5、实践验证

命令:object encoding key ,获取数据底层的数据结构

1)整数类型示例如下:

图片描述

2)短字符串示例如下:

图片描述

3)长字符串示例如下:

图片描述

 疑问:至此,我们知道了embstr、字符串对象, 但是动态字符串的结构还是没说清楚啊,你是不是在逗我?
靓仔疑问,再一次出现,别急,继续往下看

图片描述

三、动态字符串

众所周知,Redis 是用 C 语言写的,但是对于 Redis 的字符串,却不是 C 语言中的字符串(即以空字符 ’

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/3324/viewspace-2825125/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 层叠与 z-index
请登录后发表评论 登录
全部评论

注册时间:2019-08-14

  • 博文量
    89
  • 访问量
    808