Redis中String数据结构为什么以长度44为embstr和raw实现的分界线?

​ 一道常见Redis面试题。

​ 在Redis的String数据结构中,当字符串的实际长度小于44且包含非整数字符时底层编码方式为embstr。当超过44时使用raw底层编码方式。

​ 那么为什么要以字符串的长度44为分界线呢?

信息一

​ 首先要分析embstr和raw编码格式的区别:首先Redis中所有的数据结构都是通过redisObject结构体描述的,其中的type字段标识了当前对象使用的数据结构(string、list、set等),encoding字段标识了当前对象采用的编码方式(ziplist、listpack、intset、skiplist等)。而embstr编码方式是为了提高cpu寻址效率在redisObject之后直接存储具体字符串的数据内容。而raw是在redisObject上通过维护一个指向堆上的内存空间存储具体的字符串内容。

信息二

​ 内存分配器都是按照2^n进行分配的,同时cpu cache line最小访问单位为64个字节。因此为了实现cpu高效寻址,64个字节的内存空间是一个阈值。而Redis中操作对象的单位是通过redisObject。

分析如下

​ redisObject的数据结构如下:

cpp 复制代码
#define LRU_BITS 24
typedef struct redisObject {
    unsigned type:4;
    unsigned encoding:4;
    unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
                            * LFU data (least significant 8 bits frequency
                            * and most significant 16 bits access time). */
    int refcount;
    void *ptr;
} robj;

​ type字段占用4个bit位,encoding占用4个bit位,LRU_BITS为24, lru字段占用24个bit位即3个字节。refcount字段占用4个字节。ptr字段在64位系统下,占用8个字节。加在一起 1 + 3 + 4 + 8 = 16个字节。即redisObject结构体中需要占用16个字节。

​ 而ptr字段具体指向了实际的string编码结构对象,即sds。sds的结构有sds8、sds16、sds32、sds64。此时最大的寻址空间才为64个字节,因此选用最小的sds8即可。

​ sds8数据结构如下:

cpp 复制代码
struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; /* used */
    uint8_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};

​ len字段和alloc字段为uint8_t,占用1个字节,flags占用1个字节。总计1 + 1 + 1 = 3个字节。

​ 此时总计描述一个字符串信息需要使用的头信息占用16 + 3 = 19个字节。而string数据结构在设计上是兼容C语言字符串的。因此需要在末尾加上'\0'字符。还需要占用1个字节。此时总计19 + 1 = 20个字节。

​ 64 - 20 = 44个字节。因此当字符串长度小于44个字节长度时,使用embstr编码类型可以极大提高redis的查询效率和存储效率。所以string数据结构使用字符串长度为44作为embstr和raw编码类型的分界线。

更多资料:0voice · GitHub

相关推荐
玄同7658 分钟前
SQLite + LLM:大模型应用落地的轻量级数据存储方案
jvm·数据库·人工智能·python·语言模型·sqlite·知识图谱
吾日三省吾码10 分钟前
别只会“加索引”了!这 3 个 PostgreSQL 反常识优化,能把性能和成本一起打下来
数据库·postgresql
chian-ocean11 分钟前
百万级图文检索实战:`ops-transformer` + 向量数据库构建语义搜索引擎
数据库·搜索引擎·transformer
long31625 分钟前
Aho-Corasick 模式搜索算法
java·数据结构·spring boot·后端·算法·排序算法
小Tomkk31 分钟前
数据库 变更和版本控制管理工具 --Bytebase 安装部署(linux 安装篇)
linux·运维·数据库·ci/cd·bytebase
qq_12498707531 小时前
基于JavaWeb的大学生房屋租赁系统(源码+论文+部署+安装)
java·数据库·人工智能·spring boot·计算机视觉·毕业设计·计算机毕业设计
倒流时光三十年1 小时前
SpringBoot 数据库同步 Elasticsearch 性能优化
数据库·spring boot·elasticsearch
forestsea2 小时前
深入理解Redisson RLocalCachedMap:本地缓存过期策略全解析
redis·缓存·redisson
码农小卡拉2 小时前
深入解析Spring Boot文件加载顺序与加载方式
java·数据库·spring boot
佛祖让我来巡山2 小时前
Redis 为什么这么快?——「极速快递站」的故事
redis·redis为什么快?