一、源码结构全景Redis 7.2.13
先了解 7.2.13 的源码布局,这是理解演进的基础:
redis-7.2.13/src/├── server.h # 核心头文件:redisObject、client、server 结构体├── server.c # 主程序:main()、事件循环、命令分发├── anet.c / anet.h # 网络封装(ANET = Redis networking)├── ae.c / ae_*.c # 事件循环抽象层(epoll/kqueue/evport/select)├── connection.h # 连接抽象(socket/Unix/TCP/TLS)│├── [数据结构和命令]│ ├── t_string.c # String 类型│ ├── t_hash.c # Hash 类型│ ├── t_list.c # List 类型│ ├── t_set.c # Set 类型│ ├── t_zset.c # Sorted Set 类型│ ├── t_stream.c # Stream 类型(Redis 5.0+)│ ├── t_eval.c # Lua 脚本│ ├── bitops.c # 位操作│ └── hyperloglog.c # HyperLogLog│├── [集群]│ ├── cluster.c # 集群管理│ └── cluster.h│├── [持久化]│ ├── aof.c # AOF 持久化│ ├── rdb.h / rdb.c # RDB 格式和操作│ └── bio.c # Background I/O 后台线程│├── [复制]│ └── replication.c # 主从复制(PSYNCv2)│├── [安全]│ └── acl.c # ACL 访问控制(Redis 6.0+)│├── [模块系统]│ ├── redismodule.h # 模块 API 头文件│ └── module.c / moduletype.c│├── [其他核心]│ ├── dict.c # 字典(Hash 表实现)│ ├── quicklist.c # List 的压缩列表实现│ ├── sds.c # 简单动态字符串│ ├── rax.c # Radix Tree(Stream 索引)│ ├── latency.c # 延迟监控│ ├── config.c # 配置解析│ └── commands.def # 命令定义(机器可读)│└── [工具] ├── redis-cli.c # 客户端工具 └── cli_common.c # 共享 CLI 代码
二、核心数据结构:理解一切的起点
2.1 redisObject — Redis 对象的基石
// server.h 中定义,贯穿整个 Redis 4→7 始终的核心结构struct redisObject { unsigned type:4; // 类型:STRING/LIST/HASH/SET/ZSET/... unsigned encoding:4; // 编码:int/embstr/hashtable/ziplist/listpack/... unsigned lru:LRU_BITS; // LRU 或 LFU(Redis 4 开始支持 LFU) int refcount; // 引用计数(零拷贝的基础) void *ptr; // 指向实际数据};
演进:
-
Redis 4.0 之前:只有 LRU(最近最少使用)
- Redis 4.0 新增 LFU
(Least Frequently Used):lru 字段的低 16 位存访问时间,高 8 位存频率计数
2.2 client — 连接与请求的封装
struct client { int fd; // socket 文件描述符 sds querybuf; // 累积请求缓冲区 int argc; // 命令参数个数 robj **argv; // 命令参数 redisDb *db; // 当前数据库 uint64_t flags; // 客户端状态标志(Redis 4→7 持续膨胀) list *reply; // 回复缓冲区(链表) char buf[PROTO_REPLY_CHUNK_BYTES]; // 固定大小回复缓冲(16KB) // ... 大量字段持续增加};
2.3 server — 全局单例
struct redisServer { redisDb *db; // 数据库数组 dict *commands; // 命令表(Redis 7 新增命令路由优化) dict *orig_commands; // 原始命令映射 list *clients; // 所有客户端连接 client *master; // 主节点(如果是从节点) aeEventLoop *el; // 事件循环 // ... 数百个字段};
三、Redis 4.0:模块化时代的起点
3.1 核心变化
|
|
|
| Module API |
|
| LFU 模式 |
淘汰策略新增 LFU(Least Frequently Used)
|
| 混合 AOF |
AOF + RDB 混合持久化(aof-use-rdb-preamble)
|
| MEMORY USAGE |
|
| SWAPDB |
|
| TLS |
|
3.2 LFU 原理详解
// redisObject.lru 字段在 LFU 模式下的布局(24 位)// LFU implementation: 16 bits for idle time, 8 bits for frequency// 高 16 位:自 LFU 初始化以来的分钟数(逻辑时钟)// 低 8 位:访问频率计数器(0-255)#define LFU_INIT_VAL 5 // 初始频率// 频率衰减:当对象未被访问时,频率会随时间衰减uint8_t LFULogIncr(uint8_t counter) { if (counter < 255) { double r = (double)rand() / RAND_MAX; double base = (counter - LFU_INIT_VAL); if (base > 0) counter = counter + (1/(base+1)); else counter++; } return counter;}
3.3 模块系统架构
┌─────────────────────────────────────────┐│ Redis Module System ││ ││ redisModule.h(模块 API 头文件) ││ ↓ ││ Module Type Registry ││ ↓ ││ ┌───────────────────────────────────┐ ││ │ Module A │ Module B │ Module C │ ││ │ (RediSQL) │ (ReJSON) │ (vector) │ ││ └───────────────────────────────────┘ ││ ↓ ││ Redis Core(server.c / server.h) │└─────────────────────────────────────────┘
四、Redis 5.0:Stream 的诞生
4.1 核心变化
|
|
|
| Redis Stream |
|
| Redis Cluster 改进 |
|
| 客户侧缓存(Client-side caching) |
|
| 新的 Redis 异步线程 |
|
| ZPOPMAX / BZPOPMAX |
|
| LOADAVERAGE |
|
4.2 Stream 原理
Stream 是 Redis 5.0 最重要的数据结构创新:
// t_stream.c 中的核心结构typedef struct stream { rax *rax; // Radix Tree(压缩前缀树),存储所有条目 uint64_t length; // 条目数量 streamID last_id; // 最后一条的 ID rax *cgroups; // 消费者组(Consumer Groups)} stream;// Stream ID:时间戳 + 序列号typedef struct streamID { uint64_t ms; // Unix 毫秒时间戳 uint64_t seq; // 序列号} streamID;Stream 内部结构(Radix Tree 存储):root └── [0-9] → node → ... ├── "1520000000000-0" → field1:value1, field2:value2 ├── "1520000000000-1" → ... └── "1520000001234-99" → ...Consumer Group 消费模型:┌─────────────────────────────────────────────────┐│ Stream: mystream ││ 1520000000000-0 → {field: value} ││ 1520000000000-1 → {field: value} ││ 1520000000000-2 → {field: value} ││ 1520000000000-3 → {field: value} │└─────────────────────────────────────────────────┘ ▲ ┌───────────┴───────────┐ Consumer Group A Consumer Group B last_delivered_id: last_delivered_id: 1520000000000-1 1520000000000-0 │ │ ▼ ▼ Pending Entries List (PEL) → 已ACK的自动清除
4.3 客户侧缓存(Client-side caching)原理
传统缓存模式:Client ────► Redis Server ────► 客户端本地缓存(自己管理失效) ▲ │ 网络往返延迟Client-side caching 模式:Redis Server ────[失效通知]───► Client ▲ ▲ │ │ └────[请求/响应]────────────┘失效流程:1. Client 发送 CLIENT TRACKING ON2. Redis 记录该 Client 订阅的 Key3. 任何 Client 修改这些 Key 时,Redis 主动推送 INVALIDATE 消息4. 本地缓存立即失效,无需轮询
五、Redis 6.0:安全与性能的飞跃
5.1 核心变化
|
|
|
| RESP3 |
|
| ACL v2 |
|
| SSL/TLS |
|
| I/O Threads |
多线程 I/O(实验性,6.0 是雏形,7.0 完善)
|
| Threaded I/O |
io-threads-do-reads yes
|
| Client-output-buffer-limit |
|
| DISCARD |
|
| 功能:COMMAND INFO |
|
5.2 ACL 核心原理
// acl.c 中的 ACL 结构typedef struct { uint64_t bitfield; // 位图表示权限 list *patterns; // Key 允许模式(如 "cache:*") list *commands; // 允许的命令(如 "+get +set -del") char *passwords; // 密码(支持多个) char *nkeys; // Key 数量限制 char *channels; // Pub/Sub 通道限制} user;// ACL 规则示例# 用户定义user reader on >password ~cached:* -@all +getuser writer on >password ~* +@write +@readuser admin on >password ~* +@admin +@dangerous +allkeys
5.3 RESP3 vs RESP2
RESP2(Redis 4-5.x 默认):+OK\r\n:100\r\n+string\r\n$-1\r\n (nil)RESP3(Redis 6+):+OK\r\n:100\r\n=string\r\n (类型前缀变化)#t\r\n (true)#f\r\n (false):123\r\n>100\r\n (double)~[1,2,3]\r\n (set 类型)%{key:val}\r\n (map 类型)
5.4 I/O Threads 原理
// Redis 6.0 引入多线程 I/O,但处理逻辑仍然单线程// 线程分工:// Main Thread:协议解析 + 命令执行 + 响应生成// I/O Threads:读取客户端请求 + 写入响应到 socket(可选)// io-threads 配置:// io-threads 4 → 4 个 I/O 线程// io-threads-do-reads yes → I/O 线程也处理读请求// 注意:命令执行(command execution)始终在主线程// 多线程只加速了:read() / write() / accept() / connect()
六、Redis 7.0:架构重构的分水岭
6.1 核心变化
|
|
|
| Redis Functions |
|
| Shard-level Pub/Sub |
|
| ACL SELECTOR |
|
| Multi-part AOF |
|
| 新的 Shard-level replication |
|
| Command introspection |
|
| Commands .def 文件 |
|
| cluster-announce-* |
|
6.2 Redis Functions vs Lua Scripts
Redis 6.x Lua 脚本问题:.脚本不可复用(每次 EVAL 上传).无命名空间管理.版本控制困难.无法热更新Redis 7.x Functions:┌─────────────────────────────────────────┐│ LIBRARY(函数库) ││ #!js name=mylib ││ functionwrite_key(key, value) { ││ redis.call('SET', key, value) ││ } ││ redis.register_function(write_key) │└─────────────────────────────────────────┘ │ ▼ FUNCTION LOAD → 函数注册到 Redis FUNCTION LIST → 列出所有函数 FCALL write_key mykey myvalue → 调用 FUNCTION FLUSH → 清空所有函数
6.3 Multi-part AOF
Redis 7.0 之前(单 AOF):appendonly.aof ├── base: RDB 格式(初始全量) └── incr: AOF 命令增量Redis 7.0 Multi-part AOF:appendonlydir/ ├── base.${timestamp}.aof → RDB 格式全量 ├── incr.${timestamp}.aof → 增量 AOF ├── incr.${timestamp}.aof.idx → 索引 └── manifest → 文件清单(协调各部分)加载顺序:manifest → base → 按顺序重放 incr
6.4 命令定义文件(commands.def)
# Redis 7.0 引入的机器可读命令定义# src/commands.def 中每个命令的定义格式{ "GET": { "summary": "Get the value of a key", "complexity": "O(1)", "arguments": [ {"name": "key", "type": "key", "key": {"flags": ["RO"]}} ], "flags": ["READONLY", "FAST"] }}
七、Redis 7.2:性能与安全的持续进化
7.1 性能优化(7.2 GA 引入)
|
|
|
|
|
|
PSUBSCRIBE / PUNSUBSCRIBE
|
|
|
|
|
SCAN / SSCAN / HSCAN / ZSCAN
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7.2 事件循环的多路复用
// ae.c - Redis 事件循环抽象层,同时支持 4 种 I/O 多路复用:ae_select.c → select() (POSIX 通用,跨平台)ae_epoll.c → epoll_wait() (Linux,高性能)ae_kqueue.c → kqueue() (macOS/BSD,高性能)ae_evport.c → port_getn() (Solaris/Illumos,高性能)// Redis 启动时自动选择最高效的后端:// Linux → epoll// macOS → kqueue// 其他 → select(兜底)// aeEventLoop 结构typedef struct aeEventLoop { int maxfd; // 最大 fd 编号 long long timeEventNextId; aeFileEvent *events; // 文件事件数组 aeFiredEvent *fired; // 已触发事件数组 aeTimeEvent *timeEventHead; int apidata; // 平台特定数据(epoll_fd / kqueue_fd) enum aeEventLoopFlags flags;} aeEventLoop;
八、演进全景图
┌─────────────────────────────────────────────────────────────────────────────┐│ Redis 4.0 → 7.2.13 演进时间线 │├─────────────────────────────────────────────────────────────────────────────┤│ ││ 2017-07 Redis 4.0 GA ││ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ││ │ Module │ │ LFU │ │ 混合AOF │ │ MEMORY │ │ SWAPDB │ ││ │ API │ │ 淘汰策略 │ │ (RDB+AOF)│ │ USAGE │ │ │ ││ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ ││ ││ 2018-10 Redis 5.0 GA ││ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ││ │ Stream │ │ CSM │ │ UNLINK │ │ ZPOPMAX │ │ 动态 HZ │ ││ │ (Kafka式)│ │ 客户端 │ │ 异步删除 │ │ /BZPOPMAX│ │ 调整 │ ││ │ │ │ 缓存 │ │ │ │ │ │ │ ││ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ ││ ││ 2019-05 Redis 6.0 GA ││ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ││ │ RESP3 │ │ ACL v2 │ │ I/O │ │ SSL/TLS │ │ 大量 │ ││ │ 协议 │ │ 细粒度 │ │ 多线程 │ │ 原生支持 │ │ 安全修复 │ ││ │ │ │ 权限 │ │ (实验) │ │ │ │ (CVE) │ ││ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ ││ ││ 2021-09 Redis 7.0 GA ││ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ││ │ Functions│ │ Multi- │ │ Shard │ │ ACL │ │ 命令定义 │ ││ │ (替代Lua)│ │ part AOF │ │ level │ │ SELECTOR │ │ 机器可读 │ ││ │ │ │ │ │ Pub/Sub │ │ │ │ (.def) │ ││ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ ││ ││ 2023-08 → 2026-02 Redis 7.2.x(持续维护) ││ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ││ │ 性能优化 │ │ 大量 │ │ PSUBSCRIBE│ │ HyperLog │ │ 安全修复 │ ││ │ PSUBSCRIBE│ │ Lua RCE │ │ O(N*M→ │ │ Log 漏洞 │ │ (7.2.13)│ ││ │ O(N)优化 │ │ 修复 │ │ O(N) │ │ 修复 │ │ │ ││ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ ││ │└─────────────────────────────────────────────────────────────────────────────┘
九、源码层面的关键演进
9.1 内存分配器
// Redis 4.0 之前:jemalloc 是 Linux 默认(已有)// Redis 4-7:无变化,jemalloc 仍是默认分配器// 切换方式:#define make//jemalloc(默认 Linux)→ libc mallocmake MALLOC=libc//jemalloc(macOS 默认)→ jemallocmake MALLOC=jemalloc
9.2 持久化架构演进
Redis 3.x(单一 RDB): BGSAVE → dump.rdb(全量快照)Redis 4.x(RDB + AOF 混合): BGSAVE → dump.rdb AOF → appendonly.aof(增量命令) 两种同时开,互补长短Redis 7.x(Multi-part AOF): appendonlydir/ base.${ts}.aof → RDB 格式(定期生成) incr.${ts}.aof → 增量命令流 manifest → 协调文件 → 加载更快,重写更高效
9.3 复制协议演进
Redis 3.x:PSYNCv1 - 完全同步(SYNC)或部分同步(PSYNC) - 主库崩溃后从库需要全量同步Redis 4.x:无大变化,PSYNCv1 继续Redis 5.x:无大变化Redis 6.x:PSYNCv2(改进) - 引入 Replica Offset Tracking - 更好处理网络分区场景Redis 7.x: Shard-level replication → 集群模式下副本可以跨分片复制
十、总结:每个版本的核心贡献
|
|
|
|
| 4.0 |
|
|
| 5.0 |
|
|
| 6.0 |
RESP3 + ACL v2 + I/O Threads
|
|
| 7.0 |
Functions + Multi-part AOF
|
|
| 7.2 |
|
|