redis字符串
redis 3.2前sds结构
struct sds{ int len; // 已占用的字节数 int free; // 剩余可以字节数 char buf[]; // 存储字符串的数据空间 }
3.2后,这样就可以针对不同长度的字符串申请相应的存储类型,从而有效的节约了内存使用。
typedef char *sds; struct __attribute__ ((__packed__)) sdshdr5 { // 对应的字符串长度小于 1<<5 unsigned char flags; char buf[]; }; struct __attribute__ ((__packed__)) sdshdr8 { // 对应的字符串长度小于 1<<8 uint8_t len; /* 已使用长度,1 字节存储 */ uint8_t alloc; /* 总长度 */ unsigned char flags; char buf[]; // 真正存储字符串的数据空间 }; struct __attribute__ ((__packed__)) sdshdr16 { // 对应的字符串长度小于 1<<16 uint16_t len; /* 已使用长度,2 字节存储 */ uint16_t alloc; unsigned char flags; char buf[]; }; struct __attribute__ ((__packed__)) sdshdr32 { // 对应的字符串长度小于 1<<32 uint32_t len; /* 已使用长度,4 字节存储 */ uint32_t alloc; unsigned char flags; char buf[]; }; struct __attribute__ ((__packed__)) sdshdr64 { // 对应的字符串长度小于 1<<64 uint64_t len; /* 已使用长度,8 字节存储 */ uint64_t alloc; unsigned char flags; char buf[]; };
字符串类型:int、embstr、raw,当字符串长度大于44字节,就会从embstr转raw。
为什么是 44 字节?
在 Redis 中,如果 SDS 的存储值大于 64 字节时,Redis 的内存分配器会认为此对象为大字符串,并使用 raw 类型来存储,当数据小于 64 字节时(字符串类型),会使用 embstr 类型存储。既然内存分配器的判断标准是 64 字节,那为什么 embstr 类型和 raw 类型的存储判断值是 44 字节?
这是因为 Redis 在存储对象时,会创建此对象的关联信息,redisObject 对象头和 SDS 自身属性信息,这些信息都会占用一定的存储空间,因此长度判断标准就从 64 字节变成了 44 字节。
在 Redis 中,所有的对象都会包含 redisObject 对象头。 redisObject 对象的源码:
typedef struct redisObject { unsigned type:4; // 4 bit。对象的数据类型,例如:string、list、hash 等,占用 4 bits 也就是半个字符的大小; unsigned encoding:4; // 4 bit。对象数据编码,占用 4 bits unsigned lru:LRU_BITS; // 3 个字节。记录对象的 LRU(Least Recently Used 的缩写,即最近最少使用)信息,
// 内存回收时会用到此属性,占用 24 bits(3 字节) int refcount; // 4 个字节。引用计数器,占用 32 bits(4 字节) void *ptr; // 8 个字节。对象指针用于指向具体的内容,占用 64 bits(8 字节) } robj;
redisObject 总共占用 0.5 bytes + 0.5 bytes + 3 bytes + 4 bytes + 8 bytes = 16 bytes(字节)。
从 SDS 的源码可以看出,SDS 的存储类型一共有 5 种:SDSTYPE5、SDSTYPE8、SDSTYPE16、SDSTYPE32、SDSTYPE64,在这些类型中最小的存储类型为 SDSTYPE5,但 SDSTYPE5 类型会默认转成 SDSTYPE8。
SDS_TYPE8源码:
struct __attribute__ ((__packed__)) sdshdr8 { uint8_t len; // 1 byte uint8_t alloc; // 1 byte unsigned char flags; // 1 byte char buf[]; };
可以看出除了内容数组(buf)之外,其他三个属性分别占用了 1 个字节,最终分隔字符等于 64 字节,减去 redisObject 的 16 个字节,再减去 SDS 自身的 3 个字节,再减去结束符 \0
结束符占用 1 个字节,最终的结果是 44 字节(64-16-3-1=44),内存占用如下图所示:


字符串类型可用作为:页面数据缓存,可以缓存一些文章详情信息等;数字计算与统计,例如计算页面的访问次数;也可以用作 Session 共享,用来记录管理员的登录信息等。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报