占用演示

代码计算如图:

其中使用redis工具查询,占用如下:

Redis封装结构

结构

redis中,所有的对象,都是基于Redis封装结构(Redis Object)展开的,其结构如下:

typedef struct redisObject {
    // 数据类型 (4 bits)
    unsigned type:4;
    // 内部编码方式 (4 bits)
    unsigned encoding:4;
    // LRU 时间 (24 bits) 或 LFU 计数 (8 bits) + 访问时间 (16 bits)
    unsigned lru:LRU_BITS; // 通常定义为 24 bits
    // 引用计数 (32 bits)
    int refcount;
    // 指向实际数据存储的指针 (64-bit system: 8 bytes)
    void *ptr;
} robj;

RedisObject字段详解

字段名

位宽/类型

可能取值

作用

备注

type

unsigned (4 bits)

OBJ_STRING (0):字符串

OBJ_LIST (1):列表

OBJ_SET (2):集合

OBJ_ZSET (3):有序集合

OBJ_HASH (4):哈希

OBJ_MODULE (5):模块

OBJ_STREAM (6):流

标识数据类型决定对象支持的操作(如 GET 只能操作字符串类型)

命令执行时会先检查 type 是否匹配

encoding

unsigned (4 bits)

字符串:

OBJ_ENCODING_INT:整数

 - OBJ_ENCODING_EMBSTR:嵌入式字符串

 - OBJ_ENCODING_RAW:SDS字符串

列表:

 - OBJ_ENCODING_QUICKLIST:快速列表

 - OBJ_ENCODING_ZIPLIST:压缩列表(旧) 

OBJ_ENCODING_LINKEDLIST:链表(旧)

哈希:

 - OBJ_ENCODING_ZIPLIST:压缩列表

 - OBJ_ENCODING_HT:哈希表

集合:

 - OBJ_ENCODING_INTSET:整数集合

 - OBJ_ENCODING_HT:哈希表

有序集合:

 - OBJ_ENCODING_ZIPLIST:压缩列表

 - OBJ_ENCODING_SKIPLIST:跳表

标识底层数据结构

实现同类型数据的不同存储方式核心内存优化机制

Redis 根据数据特征自动转换编码(如小哈希用 ziplist,大数据转 hashtable)通过配置参数控制转换阈值(如 hash-max-ziplist-entries

lru

unsigned (24 bits)

LRU 模式: 

- 存储最后访问时间戳(低 24 位)

LFU 模式:

 - 高 8 位:访问频率计数器 (ldt)

 - 低 16 位:最后递减时间 (logc)

实现内存淘汰策略 - LRU:淘汰最久未访问 - LFU:淘汰访问频率最低

模式由 maxmemory-policy 配置决定LFU 计数器会随时间衰减

refcount

int (32 bits)

≥1:正常对象引用计数

INT_MAX:共享对象(如小整数 0-9999)

引用计数垃圾回收计数归零时自动释放内存支持对象共享节省空间

对象被键引用、Lua 脚本使用时计数增加共享对象必须不可变(如小整数)

ptr

void* (指针)

指向具体数据结构:

 - 整数:直接存储 long 值(非指针)

 - 字符串:指向 sds 结构

 - 列表:指向 quicklist

 - 哈希:指向 dict 或 ziplist

 - 集合:指向 intset 或 dict 

- 有序集合:指向 zset(含跳表和字典)

存储实际数据根据 encoding 指向对应底层结构

Bitmap

基于理论的占用计算

一个 bit 来标记一个状态:

  • 1 Byte(字节) = 8 bit(比特位)

  • 理论字节数 = 1,000,000/8=125,0001,000,000/8=125,000 Bytes

  • 理论 KB 数 = 125,000/1024≈122.07 KB

理论值就是 约 122 KB。

原因:

bitmap在redis中,实际还是基于string实现的,string底层数据结构SDS,结构如下:

  • 长度 len字段:占用4字节,表示已用长度

  • 已分配长度 alloc字段:占用4字节,表示已用长度

  • buf字节数组:保存实际的数据,基于redis是C语言实现,数组值最后占用一位。值为“\0”,额外占用一个字节,计算总长度时,需要减去一字节。

Bloom

已知参数:

  • n=1,000,000(元素数量)

  • p=0.0001(误判率)

布隆过滤器公式:

具体计算:

内存占用计算

加上 Redis 数据结构开销:

  • Redis 的布隆过滤器(如 RedisBloom 模块)会有少量元数据开销

  • 实际占用约 2.3 - 2.4 MB

占用对比

数据结构

100万数据内存占用

特点

Bitmap

122 KB

适合连续整数ID,精确存在判断

Bloom

2.46 MB

适合任意数据类型,有误判率(万分之一)

区别:

  • Bitmap 是 精确 的,但只能用于整数

  • 布隆过滤器可以处理 任意数据类型,但存在误判

  • 误判率越低,布隆过滤器需要的空间越大