第六篇:内存管理与持久化机制
1. 引言
Redis作为一个内存数据库,其内存管理和持久化机制直接影响性能和数据可靠性。Redis通过自定义内存分配器优化内存使用,同时提供RDB和AOF两种持久化方式保证数据不丢失。本篇将深入剖析Redis的内存管理(zmalloc.c
)以及RDB(rdb.c
)和AOF(aof.c
)的实现细节。
2. 内存管理
2.1 Redis的内存分配器
Redis默认使用jemalloc
(可在deps/
中找到),也支持tcmalloc
或标准libc
。自定义封装在zmalloc.c
中。
代码片段(zmalloc.h
):
|
|
硬核解析:
zmalloc()
:调用jemalloc
分配内存,记录使用量。zmalloc_size()
:返回实际分配块大小,用于内存统计。- 优势:减少碎片,提升分配效率。
代码片段(zmalloc.c
):
|
|
硬核解析:
PREFIX_SIZE
:额外空间存储元数据(通常8字节)。update_zmalloc_stat_alloc()
:更新全局内存统计。
3. 持久化机制
Redis提供两种持久化方式:RDB(快照)和AOF(日志)。
3.1 RDB持久化(rdb.c
)
RDB通过生成内存数据的快照保存到磁盘。
代码片段(rdbSave()
):
|
|
硬核解析:
rio
:Redis的I/O抽象层,支持缓冲写。- 格式:RDB文件包含版本号、数据库键值对和校验和。
后台保存(rdbSaveBackground()
):
|
|
硬核解析:
- fork():创建子进程,避免阻塞主线程。
- COW(Copy-On-Write):子进程共享内存,快照时仅复制修改页面。
Mermaid RDB流程:
graph TD
A["rdbSaveBackground()"] --> B["fork()"]
B --> C{"子进程?"}
C -->|Yes| D["rdbSave()"]
D --> E["写RDB文件"]
E --> F["exit(0)"]
C -->|No| G["返回C_OK"]
3.2 AOF持久化(aof.c
)
AOF记录每次写操作,类似日志追加。
代码片段(feedAppendOnlyFile()
):
|
|
硬核解析:
catClientCommandString()
:将命令转为字符串(如SET key value
)。rioWrite()
:追加到缓冲区,定期刷盘。
AOF重写(rewriteAppendOnlyFileBackground()
):
|
|
硬核解析:
- 重写目的:压缩AOF文件,合并重复操作。
- 后台执行:fork子进程,主线程继续服务。
Mermaid AOF重写流程:
graph TD
A["rewriteAppendOnlyFileBackground()"] --> B["fork()"]
B --> C{"子进程?"}
C -->|Yes| D["rewriteAppendOnlyFile()"]
D --> E["生成临时AOF"]
E --> F["替换原文件"]
F --> G["exit(0)"]
C -->|No| H["返回C_OK"]
4. 内存与持久化的优化
- 内存:
jemalloc
减少碎片。- LRU淘汰(
evictionPoolPopulate()
)回收内存。
- 持久化:
- RDB快照适合快速恢复。
- AOF日志保证数据完整性,结合重写控制文件大小。
5. 总结与调试建议
- 收获:理解Redis内存分配与持久化实现。
- 调试技巧:
- 用
INFO MEMORY
查看内存统计。 - 用
strace
跟踪fork
和文件写操作。
- 用
- 下一步:探索主从复制与集群。