当你对 redis 说你中意的女孩是 Mia
字数 1937 2025-08-11 08:36:09

Redis 内部存储机制详解

一、Redis 概述

Redis (Remote Dictionary Server) 是一个开源的、支持网络的、基于内存亦可持久化的 Key-Value 数据库,使用 ANSI C 语言编写,并提供多种语言的 API。

二、Redis 数据存储结构

2.1 键值对存储基础

当执行 SET myLove Mia 命令时,Redis 内部会进行以下处理:

  1. 将 key:myLove 和 value:Mia 包装成一个 dictEntry 对象
  2. 创建一个 redisObject 对象来存储值

2.2 dictEntry 结构

dictEntry 是 Redis 存储键值对的基本单元,结构如下:

typedef struct dictEntry {
    // 键
    void *key;
    
    // 值
    union {
        void *val;    // 指向具体redisObject
        uint64_t u64;
        int64_t s64;
    } v;
    
    // 指向下个哈希表节点,形成链表
    struct dictEntry *next;
} dictEntry;
  • Redis 内部使用一个大 hashmap 存储数据,通过数组实现 hash
  • key 冲突通过链表解决
  • 每个 dictEntry 存储一个 key-value 对,value 为 redisObject

2.3 Key 的存储

Key ("myLove") 不是直接以字符串存储,而是存储在 SDS (Simple Dynamic String) 结构中。

2.4 redisObject 结构

Value ("Mia") 存储在 redisObject 中,结构如下:

typedef struct redisObject {
    // 类型 4bits
    unsigned type:4;
    
    // 编码方式 4bits
    unsigned encoding:4;
    
    // LRU 时间(相对于 server.lruclock) 24bits
    unsigned lru:22;
    
    // 引用计数 Redis里面的数据可以通过引用计数进行共享 32bits
    int refcount;
    
    // 指向对象的值 64-bit
    void *ptr;
} robj;
  • ptr:指向具体的数据结构地址
  • type:表示对象类型(String, List, Hash, Set, Zset 之一)
  • encoding:表示底层使用的编码

2.5 Redis 底层数据结构

Redis 对象底层有八种数据结构:

  1. REDIS_ENCODING_INT (long 类型的整数)
  2. REDIS_ENCODING_EMBSTR (编码的简单动态字符串)
  3. REDIS_ENCODING_RAW (简单动态字符串)
  4. REDIS_ENCODING_HT (字典)
  5. REDIS_ENCODING_LINKEDLIST (双端链表)
  6. REDIS_ENCODING_ZIPLIST (压缩列表)
  7. REDIS_ENCODING_INTSET (整数集合)
  8. REDIS_ENCODING_SKIPLIST (跳跃表和字典)

2.6 查看 redisObject 信息

# 查看 key 对应 value 的 redisObject 类型
type key
type myLove

# 查看 key 对应 value 的 redisObject 详细信息
debug object key
debug object myLove

不同 value 类型在 redisObject 中的表现:

  • string 和 int 类型的 type 可能相同,但 encoding 不同

三、Redis 持久化机制

3.1 RDB 持久化

  • 将数据以二进制形式写入磁盘文件
  • 默认持久化方式

3.2 AOF 持久化

AOF (Append Only File) 持久化记录所有会更改 Redis 数据的命令:

  1. 配置 (redis.conf):

    appendonly yes
    dir ./
    appendfilename appendonly.aof
    
  2. 同步过程

    • 命令传播:Redis 将执行完的命令、参数等信息发送到 AOF 程序
    • 缓存追加:AOF 程序将命令转换为 RESP 协议格式,追加到 AOF 缓存
    • 文件写入和保存:AOF 缓存内容写入文件,满足条件时调用 fsync 保存到磁盘
  3. RESP 协议

    • Redis 客户端与服务器通信的序列化协议
    • 通过特殊符号区分数据类型:
      • +:单行回复
      • -:错误回复
      • ::整数回复
      • $:批量回复
      • *:多条批量回复
  4. 示例

    • 命令:SET myLove "Mia"
    • 请求数据:*3\r\n$3\r\nSET\r\n$6\r\nmyLove\r\n$3\r\nMia\r\n
    • 响应数据:+OK\r\n
  5. 文件保存

    • flushAppendOnlyFile 函数执行:
      • WRITE:将 aof_buf 缓存写入 AOF 文件
      • SAVE:调用 fsync 将文件保存到磁盘

四、键过期机制

4.1 设置键过期时间

EXPIRE myLove 999999999

4.2 过期字典

  • RedisDb 结构中的 expires 字典保存所有键的过期时间
  • 过期字典的 key 是指向键空间某个键对象的指针
  • 过期字典的 value 是 long 类型整数,表示键的过期时间(毫秒级 UNIX 时间戳)

4.3 过期键判定

  1. 检查 key 是否存在于过期字典中
  2. 获取 key 的过期时间,判断当前 UNIX 时间戳是否大于过期时间

4.4 过期键删除策略

  1. 惰性删除

    • expireIfNeeded 函数实现
    • 所有读写命令执行前都会调用此函数检查输入键
    • 如果键已过期则删除,未过期则不处理
  2. 定期删除

    • activeExpireCycle 函数实现
    • 服务器周期性操作时调用
    • 在规定时间内分多次遍历数据库,随机检查部分键的过期时间并删除过期键

五、键删除操作

DEL myLove

注意:某些情况下键可能无法被删除(如被引用计数保护的数据)

Redis 内部存储机制详解 一、Redis 概述 Redis (Remote Dictionary Server) 是一个开源的、支持网络的、基于内存亦可持久化的 Key-Value 数据库,使用 ANSI C 语言编写,并提供多种语言的 API。 二、Redis 数据存储结构 2.1 键值对存储基础 当执行 SET myLove Mia 命令时,Redis 内部会进行以下处理: 将 key:myLove 和 value:Mia 包装成一个 dictEntry 对象 创建一个 redisObject 对象来存储值 2.2 dictEntry 结构 dictEntry 是 Redis 存储键值对的基本单元,结构如下: Redis 内部使用一个大 hashmap 存储数据,通过数组实现 hash key 冲突通过链表解决 每个 dictEntry 存储一个 key-value 对,value 为 redisObject 2.3 Key 的存储 Key ("myLove") 不是直接以字符串存储,而是存储在 SDS (Simple Dynamic String) 结构中。 2.4 redisObject 结构 Value ("Mia") 存储在 redisObject 中,结构如下: ptr :指向具体的数据结构地址 type :表示对象类型(String, List, Hash, Set, Zset 之一) encoding :表示底层使用的编码 2.5 Redis 底层数据结构 Redis 对象底层有八种数据结构: REDIS_ENCODING_INT (long 类型的整数) REDIS_ENCODING_EMBSTR (编码的简单动态字符串) REDIS_ENCODING_RAW (简单动态字符串) REDIS_ENCODING_HT (字典) REDIS_ENCODING_LINKEDLIST (双端链表) REDIS_ENCODING_ZIPLIST (压缩列表) REDIS_ENCODING_INTSET (整数集合) REDIS_ENCODING_SKIPLIST (跳跃表和字典) 2.6 查看 redisObject 信息 不同 value 类型在 redisObject 中的表现: string 和 int 类型的 type 可能相同,但 encoding 不同 三、Redis 持久化机制 3.1 RDB 持久化 将数据以二进制形式写入磁盘文件 默认持久化方式 3.2 AOF 持久化 AOF (Append Only File) 持久化记录所有会更改 Redis 数据的命令: 配置 (redis.conf): 同步过程 : 命令传播 :Redis 将执行完的命令、参数等信息发送到 AOF 程序 缓存追加 :AOF 程序将命令转换为 RESP 协议格式,追加到 AOF 缓存 文件写入和保存 :AOF 缓存内容写入文件,满足条件时调用 fsync 保存到磁盘 RESP 协议 : Redis 客户端与服务器通信的序列化协议 通过特殊符号区分数据类型: + :单行回复 - :错误回复 : :整数回复 $ :批量回复 * :多条批量回复 示例 : 命令: SET myLove "Mia" 请求数据: *3\r\n$3\r\nSET\r\n$6\r\nmyLove\r\n$3\r\nMia\r\n 响应数据: +OK\r\n 文件保存 : flushAppendOnlyFile 函数执行: WRITE:将 aof_ buf 缓存写入 AOF 文件 SAVE:调用 fsync 将文件保存到磁盘 四、键过期机制 4.1 设置键过期时间 4.2 过期字典 RedisDb 结构中的 expires 字典保存所有键的过期时间 过期字典的 key 是指向键空间某个键对象的指针 过期字典的 value 是 long 类型整数,表示键的过期时间(毫秒级 UNIX 时间戳) 4.3 过期键判定 检查 key 是否存在于过期字典中 获取 key 的过期时间,判断当前 UNIX 时间戳是否大于过期时间 4.4 过期键删除策略 惰性删除 : 由 expireIfNeeded 函数实现 所有读写命令执行前都会调用此函数检查输入键 如果键已过期则删除,未过期则不处理 定期删除 : 由 activeExpireCycle 函数实现 服务器周期性操作时调用 在规定时间内分多次遍历数据库,随机检查部分键的过期时间并删除过期键 五、键删除操作 注意:某些情况下键可能无法被删除(如被引用计数保护的数据)