Redis内存模型与对象系统:深入理解redisObject
引言 在使用Redis时,我们操作的是String、Hash、List这些高层数据类型。但你是否想过:Redis是如何在内存中存储和管理这些对象的?为什么同样是存储字符串,Redis能做到如此高的性能和内存利用率? 今天我们深入Redis底层,揭开对象系统的神秘面纱。理解对象系统,是理解Redis高性能和内存优化的基础。 一、为什么需要对象系统? 1.1 直接存储的问题 假设我们不用对象系统,直接在内存中存储数据,会遇到什么问题? // 简单粗暴的方式 char* key = "user:1001"; char* value = "张三"; // 问题1:如何知道value的类型?是字符串?整数?还是列表? // 问题2:如何实现引用计数?避免重复拷贝 // 问题3:如何记录对象的访问时间?用于LRU淘汰 // 问题4:如何选择最优的底层编码?节省内存 1.2 对象系统的价值 Redis设计了一个统一的对象系统redisObject,解决了以下问题: 类型识别:明确知道对象是什么类型(String/Hash/List/Set/ZSet) 编码优化:根据数据特点自动选择最优编码方式(节省内存) 内存管理:引用计数、LRU/LFU淘汰、内存回收 命令多态:同一个命令可以作用于不同编码的对象 类型安全:避免类型错误操作(如对字符串执行LPUSH) 二、redisObject核心结构 2.1 源码定义 typedef struct redisObject { unsigned type:4; // 类型(4 bits):String、Hash、List、Set、ZSet unsigned encoding:4; // 编码(4 bits):底层实现方式 unsigned lru:24; // LRU时间戳(24 bits)或LFU数据 int refcount; // 引用计数(32 bits) void *ptr; // 指向实际数据的指针(64 bits) } robj; 结构说明: 总大小:16字节(紧凑设计,节省内存) 4 bits + 4 bits + 24 bits = 32 bits = 4字节 refcount:4字节 ptr:8字节(64位系统) 2.2 字段详解 2.2.1 type:对象类型(4 bits) #define OBJ_STRING 0 // 字符串 #define OBJ_LIST 1 // 列表 #define OBJ_SET 2 // 集合 #define OBJ_ZSET 3 // 有序集合 #define OBJ_HASH 4 // 哈希表 示例: ...