首页 > 数据库 >探索Redis的字符串设计思想

探索Redis的字符串设计思想

时间:2023-10-04 17:00:35浏览次数:37  
标签:存储 字节 探索 Redis 64 字符串 长度

探索Redis的字符串设计思想

作者:沈自在

1 引言

​ 在Redis中的字符串和我们平时Java中所写的字符串是不一样的,在Java的设计中String是由final修饰的,因此也就成就了他不可变的特性。此外,在C语言的字符标准形式中是以NULL结尾的,但是要通过strlen函数去获取长度的复杂度却是O(n)的,可还记得keys的O(n)有多么吓人。

​ 在Redis的实现中是设计了一个叫做“SDS”的结构(Simple Dynamic String),如下面源码片段所示,他的结构是一个带长度的字节数组。

struct{
  T capacity; //数组容量
  T len;  //数组长度
  byte flags; // 标识位
  byte[] content; // 数组内容
}

​ 这样的设计就很类似ArrayList了,同时它的追加机制也很类似ArrayList了。

​ 上面的SDS结构体可以看到在长度和容量处采用了 T 范型,之所以不使用int其实是作者对Redis的优化操作,如果当字符串长度很小的时候采用一个int做长度容量的空间的话就显得很浪费了。

2 存储方式

​ Redis对字符串的存储存在俩种存储方式,在长度特别短时使用embstr ,当长度大于44字节时使用raw存储,这里的设计和Redis的内存分配有莫大的关系。

​ Redis的每个对象都有一个对象头,他的结构是这样的:

struct RedisObject {
 int4 type; // 4bits
 int4 encoding; // 4bits
 int24 lru; // 24bits
 int32 refcount; // 4bytes
 void *ptr; // 8bytes,64-bit system
} robj;

​ 不同的对象具有不同的类型 type(4bit),同一个类型的 type 会有不同的存储形式encoding(4bit),为了记录对象的 LRU 信息,使用了 24 个 bit 来记录 LRU 信息。每个对象都有个引用计数,当引用计数为零时,对象就会被销毁,内存被回收。ptr 指针将指向对象内容 (body) 的具体存储位置。这样一个 RedisObject 对象头需要占据 16 字节的存储空间

image-20230405165542861

​ 如图所示,embstr 存储形式是这样一种存储形式,它将 RedisObject 对象头和 SDS 对象连续存在一起,使用 malloc 方法一次分配。而 raw 存储形式不一样,它需要两次malloc,两个对象头在内存地址上一般是不连续的。而内存分配器 jemalloc/tcmalloc 等分配内存大小的单位都是 2、4、8、16、32、64 等等,为了能容纳一个完整的 embstr 对象,jemalloc 最少会分配 32 字节的空间,如果字符串再稍微长一点,那就是 64 字节的空间。如果总体超出了 64 字节,Redis 认为它是一个大字符串,不再使用 emdstr 形式存储,而该用 raw 形式。

​ 当内存分配器分配了 64 空间时,那这个字符串的长度最大可以是多少呢?这个长度就是 44。那为什么是 44 呢?前面我们提到 SDS 结构体中的 content 中的字符串是以字节\0 结尾的字符串,之所以多出这样一个字节,是为了便于直接使用 glibc 的字符串处理函数,以及为了便于字符串的调试打印输出。

​ 看上面这张图可以算出,留给 content 的长度最多只有 45(64-19) 字节了。字符串又是以\0 结尾,所以 embstr 最大能容纳的字符串长度就是 44。

标签:存储,字节,探索,Redis,64,字符串,长度
From: https://www.cnblogs.com/shenzizai/p/17742464.html

相关文章

  • 点赞功能改进-Redis数据结构设计
        ......
  • vue中beforedistory应用
    遇到一个问题,就是我在使用全局事件总线的时候发布了一个事件,然后在a组件里面这个时间会被触发一次,在b组件里面也会触发一次.这两个组件是平级组件不是嵌套组件.然后呢,在a组件触发完之后,我去了b组件,在b组件中触发相同时间的时候,a组件的逻辑和b组件的逻辑都执行了一次.一开......
  • MongoDB 和 Redis 的区别
    在现代的应用程序开发中,数据库是不可或缺的组成部分。MongoDB和Redis是两种流行的数据库,它们在一些方面有相似之处,但在其他方面则有着显著的差异。下面,我们将探讨MongoDB和Redis的区别。数据模型MongoDB是一个面向文档的数据库,它存储的数据是以BSON(BinaryJSON)格式存......
  • 库函数之字符函数与字符串函数(上)
    前言......
  • 10.0 探索API调试事件原理
    本章笔者将通过Windows平台下自带的调试API接口实现对特定进程的动态转存功能,首先简单介绍一下关于调试事件的相关信息,调试事件的建立需要依赖于DEBUG_EVENT这个特有的数据结构,该结构用于向调试器报告调试事件。当一个程序发生异常事件或者被调试器附加时,就会产生对应的DEBUG_EVENT......
  • Centos安装Redis
    一、下载安装redis1.1新建文件夹redis,获取安装包wgethttp://download.redis.io/releases/redis-5.0.5.tar.gz11.2解压安装包tar-zxvfredis-5.0.5.tar.gz11.3进入解压后的文件目录使用make命令进行编译1.4进入src文件执行makeinstall安装redis1.5在src目录执行./redis......
  • 10.0 探索API调试事件原理
    本章笔者将通过Windows平台下自带的调试API接口实现对特定进程的动态转存功能,首先简单介绍一下关于调试事件的相关信息,调试事件的建立需要依赖于DEBUG_EVENT这个特有的数据结构,该结构用于向调试器报告调试事件。当一个程序发生异常事件或者被调试器附加时,就会产生对应的DEBUG_EVEN......
  • 前端歌谣的刷题之路-第三十五题-字符串字符统计
     目录前言题目 核心代码总结前言我是歌谣我有个兄弟巅峰的时候排名c站总榜19叫前端小歌谣曾经我花了三年的时间创作了他现在我要用五年的时间超越他今天又是接近兄弟的一天人生难免坎坷大不了从头再来歌谣的意志是永恒的放弃很容易但是坚持一定很酷本题目源自于牛客网......
  • 前端歌谣的刷题之路-第三十六题-字符串字符统计
     前言我是歌谣我有个兄弟巅峰的时候排名c站总榜19叫前端小歌谣曾经我花了三年的时间创作了他现在我要用五年的时间超越他今天又是接近兄弟的一天人生难免坎坷大不了从头再来歌谣的意志是永恒的放弃很容易但是坚持一定很酷本题目源自于牛客网微信公众号前端小歌谣题目......
  • redis中各种scan命令学习
    转自:https://blog.csdn.net/qq_40399646/article/details/109034331,这个博客讲的非常好http://jinguoxing.github.io/redis/2018/09/04/redis-scan/1.介绍keys命令可以列出所有满足特定正则字符串规则的key。但它没有offset、limit参数,会一次性返回所有满足条件的key,是遍历......