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的形式追加到文件的末尾。

相关推荐
YOU OU3 小时前
Redis基础常识与命令
数据库·redis·缓存
Database_Cool_6 小时前
OLTP 和 OLAP 区别详解:分析型数据库和事务型数据库怎么选(附阿里云 AnalyticDB MySQL 选型指南)
数据库·mysql·阿里云
爱写代码的阿森6 小时前
鸿蒙三方库 | harmony-utils之KvUtil键值型数据库操作详解
数据库·华为·harmonyos·鸿蒙·huawei
Database_Cool_7 小时前
单机 MySQL 迁移到分布式数据库方便吗?阿里云 PolarDB-X 100% MySQL 协议兼容零改造平滑迁移
数据库·分布式·mysql
姜太小白7 小时前
【MySQL】 索引优化实战:解决 WHERE 等值 + IS NULL 查询,TEXT 字段报错 1167 的完整指南
数据库·mysql
a1117768 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
窝子面8 小时前
手搓最简前后端协作-node
javascript·数据库
我的xiaodoujiao8 小时前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest
吳所畏惧8 小时前
宝塔面板Redis密码修改指南:SSH命令修改 vs 面板UI界面修改,哪个更靠谱?
运维·服务器·数据库·redis·缓存·ssh