redis学习过程

可以从github上拉一份redis来看,发现redis是用C语言来实现的。高性能kv数据库,为何高效呢?因为在内存,内存离CPU比磁盘更近,所以高效。

你可以先把 Redis 理解成一句话:

Redis 主线程不断从 socket 读命令,解析成 argv ,查命令表,调用对应函数,最后操作 db->keys 这个内存字典。

我们从第0层开始学习

cpp 复制代码
客户端
  │  (网络层)
  ▼
[1.网络/连接]  ──→  [2.命令分发]  ──→  [3.数据结构与对象]
  ae.c              server.c           object.c + t_*.c
  networking.c      command table      dict/sds/listpack...
                          │
                          ▼
                    [4.数据库语义]
                    db.c / expire.c / evict.c
                          │
            ┌─────────────┼─────────────┐
            ▼             ▼             ▼
      [5.持久化]    [6.复制/高可用]  [7.集群]
      rdb.c/aof.c   replication.c    cluster.c
                    sentinel.c

存到内存的到底是什么

struct redisObject {

unsigned type:4; // 这是什么类型?string/list/hash/set/zset...

unsigned encoding:4; // 底层用什么结构存?(同一类型可以有多种存法)

unsigned refcount : 23; // 引用计数:有多少人在用我,降到0就释放

unsigned iskvobj : 1;

unsigned metabits :8;

unsigned lru:LRU_BITS; // 上次访问时间,用于 LRU/LFU 淘汰

void *ptr; // 真正的数据在这里(指向 sds、dict、quicklist...)

};

这是整个 Redis 最核心的一个结构。 你执行 SET a 1 ,那个 "1" 在内存里就是一个 robj 。理解它:

#define OBJ_STRING 0 // 字符串

#define OBJ_LIST 1 // 列表

#define OBJ_SET 2 // 集合

#define OBJ_ZSET 3 // 有序集合

#define OBJ_HASH 4 // 哈希

typedef struct redisDb {

kvstore *keys; // ★ 所有的 key→value 都在这里(这就是"数据库"本体)

kvstore *expires; // 设置了过期时间的 key 在这里

...

dict *watched_keys; // 被 WATCH 监视的 key(事务用)

int id; // 数据库编号 0~15

...

} redisDb;

struct redisObject {

unsigned type:4; // 这是什么类型?string/list/hash/set/zset...

unsigned encoding:4; // 底层用什么结构存?(同一类型可以有多种存法)

unsigned refcount : 23; // 引用计数:有多少人在用我,降到0就释放

unsigned iskvobj : 1;

unsigned metabits :8;

unsigned lru:LRU_BITS; // 上次访问时间,用于 LRU/LFU 淘汰

void *ptr; // 真正的数据在这里(指向 sds、dict、quicklist...)

};

cpp 复制代码
1. 客户端发字节 "SET a 1"
        │
2. 网络层读进来,解析成 argv = ["SET", "a", "1"]      (robj 数组)
        │
3. 拿 "SET" 查命令表 → 找到 redisCommand → 调用 proc = setCommand
        │
4. setCommand 把值 "1" 包成一个 robj(用 INT 编码)
        │
5. 把 "a" → robj("1") 写进当前 db->keys
        │
6. 回复客户端 "+OK"

最值得学

cpp 复制代码
最值得学

- 事件驱动模型 :Redis 用事件循环处理网络 IO、定时任务、后台状态推进,是理解高性能服务端的绝佳样本。
- 简单抽象叠复杂能力 :核心就是 client 、 redisCommand 、 redisDb 、对象系统、事件循环,但上面能长出事务、Lua、复制、AOF、集群。
- 数据结构工程化 :不是教科书里的 Hash/List/Skiplist,而是 SDS、dict、quicklist、listpack、intset、rax 这些"为内存和性能妥协过"的实现。
- 命令执行管线 :从网络协议到 argv ,再到命令表和函数指针分发,这是很多数据库、网关、RPC 框架都共通的设计。
- 持久化设计 :RDB 是快照,AOF 是日志,二者组合体现了数据库系统里性能、恢复速度、可靠性之间的取舍。
- 复制与高可用 :主从复制、PSYNC、backlog、Sentinel、failover,是理解分布式系统的好入口。
- 过期与内存淘汰 :懒删除、主动过期、LRU/LFU 近似算法,非常适合学习"如何在性能和准确性之间折中"。
- 渐进式维护 :渐进式 rehash、active expire、lazyfree,把大任务拆成小步做,是高性能系统非常核心的思想。

1.理解主循环、命令分发、GET/SET 读写路径

主循环

cpp 复制代码
void aeMain(aeEventLoop *eventLoop) {
    eventLoop->stop = 0;
    while (!eventLoop->stop) {
        aeProcessEvents(eventLoop, AE_ALL_EVENTS|
                                   AE_CALL_BEFORE_SLEEP|
                                   AE_CALL_AFTER_SLEEP);
    }
}

RDB和AOF

RDB的流程是fork一个子进程,利用虚拟内存地址的写实拷贝,去全量的把数据全部拿出来。

AOF的话类似于MYSQL的binlog,记录的命令执行过程。

现代生产环境一般是复合使用的。过一段时间先frok进程去全量RDB文件,然后在此期间产生的命令在以AOF的形式追加到文件的末尾。

相关推荐
这个DBA有点耶11 小时前
NULL不是空——数据库里最反直觉的设计,90%新人踩过的坑
数据库·mysql·代码规范
这个DBA有点耶13 小时前
AI写的SQL跑崩了生产库,这锅谁背?
数据库·人工智能·程序员
镜舟科技13 小时前
Databricks 再提 LTAP,AI 时代的数据底座为何重回大一统叙事?
数据库·架构·agent
Databend14 小时前
从湖仓升级为 Agent 时代的数据控制面,Snowflake 和 Databricks 有哪些布局
大数据·数据库·agent
ClouGence17 小时前
SQL Server CDC 能放到 Always On 备库读吗?一文讲透原理与实践
数据库·sql server
先吃饱再说1 天前
存储的进化:从 MySQL 到浏览器缓存,数据到底住在哪?
数据库
Nturmoils1 天前
字段太多看不全,ksql 的展开模式和输出控制怎么用
数据库·后端
Databend2 天前
Agent 轨迹分析与归因的数据工程实践
大数据·数据库·agent
这个DBA有点耶2 天前
SQL改写进阶:标量子查询的“隐形代价”与消除实战
数据库·mysql·架构
smallyoung2 天前
数据库乐观锁深度解析:MySQL、PostgreSQL 实战 + Spring Boot 集成指南
数据库·mysql·postgresql