单点Redis的问题

一:分布式缓存-Redis持久化
1.1:RDB
1.1.1:RDB简介
RDB(Redis DataBase)是Redis提供的一种快照式持久化机制 。它会在指定的时间间隔内,将内存中的数据集以二进制的方式生成一个紧凑的压缩文件 (默认为dump.rdb),保存到磁盘上。当Redis重启时,可以通过加载这个RDB文件来恢复数据。
1.1.2:RDB工作原理
2.1 核心流程
RDB的持久化过程主要分为以下步骤:
-
Redis父进程根据配置或命令,决定需要执行RDB保存。
-
父进程调用
fork()系统调用,创建一个子进程。 -
父进程继续处理客户端请求,子进程则开始将内存中的数据写入一个临时的RDB文件。
-
子进程完成后,用这个临时文件原子地替换旧的RDB文件,然后退出。
整个过程利用操作系统**写时复制(Copy-On-Write)**技术,使得在子进程写文件期间,父进程对数据的修改不会被阻塞,内存占用也仅在修改数据时才额外增加。
2.2 fork与写时复制
-
fork()会创建一个与父进程几乎完全一样的子进程,此时父子进程共享同一块物理内存。 -
当父进程需要修改某个内存页时,操作系统才会将该页复制一份,让父进程在新页上修改,子进程继续读取原页。
-
因此,RDB子进程生成快照时,内存中的数据是fork那一刻的一个一致性快照,不会受到后续写操作的影响。
2.3 RDB文件结构
RDB文件是一个经过压缩的二进制文件,包含了以下部分:
-
固定文件头(REDIS标识及版本号)
-
数据库元信息(如数据库编号)
-
键值对数据(支持多种数据类型)
-
过期时间(如果key有设置)
-
文件结束标志(8字节校验和)
在Redis 6.2.6中,RDB文件格式已经支持模块自定义数据类型、Stream、HyperLogLog等高级结构。
1.1.3:RDB触发方式
3.1 自动触发(配置文件)
通过redis.conf中的save指令配置自动保存规则,格式为:
save <seconds> <changes>
表示在指定的秒数内,如果发生了指定次数的写操作,则自动执行一次RDB保存。
例如(默认配置):
save 900 1
save 300 10
save 60 10000
含义:
-
900秒内至少1次修改,触发保存
-
300秒内至少10次修改,触发保存
-
60秒内至少10000次修改,触发保存
可以配置多个save行,它们之间是"或"的关系。同时,Redis还维护了一个dirty计数器(记录自上次保存后有多少次写操作)和一个lastsave时间戳,用于判断是否满足条件。
3.2 手动触发
-
SAVE命令 :在主进程直接执行保存,会阻塞所有客户端请求,直到RDB完成。一般不推荐在生产环境使用。
-
BGSAVE命令:在后台异步保存,Redis会fork一个子进程来完成RDB,主进程继续处理请求。这是生产环境常用的方式。
-
SHUTDOWN命令 :当执行
SHUTDOWN关闭服务器时,如果没有开启AOF,则会自动执行一次BGSAVE。 -
主从复制 :当从节点连接到主节点,进行全量复制时,主节点会执行一次
BGSAVE,并将生成的RDB文件发送给从节点。
3.3 其他触发情况
-
执行
DEBUG RELOAD命令会触发保存(如果开启)。 -
在某些监控或运维工具中也可能触发。
1.1.4:相关配置参数
在redis.conf中,与RDB相关的常用配置有:
| 配置项 | 说明 |
|---|---|
save <seconds> <changes> |
自动保存规则 |
stop-writes-on-bgsave-error |
当最近一次BGSAVE失败时,是否拒绝写入。默认为yes,建议保持yes避免数据不一致 |
rdbcompression |
是否启用LZF压缩字符串对象,默认为yes,可减少文件大小但消耗CPU |
rdbchecksum |
是否对RDB文件生成校验和,默认为yes,推荐开启以保证文件完整性 |
dbfilename |
RDB文件名,默认为dump.rdb |
dir |
RDB文件及AOF文件的存储目录 |
1.1.5:RDB优点
-
性能高:主进程仅在fork子进程时消耗一些CPU,其余持久化工作由子进程完成,不影响客户端请求响应。
-
恢复速度快:RDB文件是紧凑的二进制数据,重启时直接加载进内存即可,远比AOF逐条重放命令快。
-
适合灾难恢复:可以将RDB文件定期归档到异地,方便做冷备份。
-
主从复制基础:全量复制依赖RDB文件,为集群扩展提供基础。
1.1.6:RDB缺点
-
数据安全性较低:因为是定期快照,如果两次保存之间发生宕机,最后一次保存后的修改数据会全部丢失。丢失量取决于保存频率。
-
fork开销 :当数据量很大时,
fork()操作本身会耗时长,可能导致主进程短暂阻塞。内存占用也因写时复制而可能翻倍(极端情况下)。 -
子进程IO压力:将整个内存数据写入磁盘,如果数据量很大,会产生较高的磁盘IO,可能影响主进程响应(取决于存储性能)。
-
不是实时的:无法做到秒级的持久化,不适合对数据安全性要求极高的场景。
1.1.7:实践建议
-
合理配置save参数 :在性能和安全之间权衡,例如
save 60 1000,保证较短间隔内有一定数量的变更时触发保存。 -
监控BGSAVE状态 :通过
INFO Persistence命令查看rdb_last_bgsave_status和rdb_last_save_time,确保后台保存正常。 -
避免不必要的手动SAVE :永远不要在生产环境使用
SAVE命令。 -
结合AOF使用:如果对数据丢失极度敏感,可开启AOF(Append Only File)持久化,两者配合可以实现更高可靠性(Redis 6.2支持混合持久化)。
-
备份管理:定期将RDB文件复制到安全位置,并保留多个版本,用于回滚或异地容灾。
-
资源规划:预估内存峰值,确保服务器有足够内存应对fork时的写时复制开销(一般至少预留30%以上内存空闲)。
1.1.8:RDB相关命令速查
-
SAVE-- 同步保存(阻塞) -
BGSAVE-- 异步保存(推荐) -
LASTSAVE-- 查看最后一次成功保存的时间戳 -
INFO Persistence-- 查看持久化相关信息 -
CONFIG SET save ""-- 禁用自动RDB
1.1.9:RDB在Redis 6.2.6中的增强
AOF和RDB混合持久化 (aof-use-rdb-preamble yes)得到了更好的体验,即AOF文件的前半部分是RDB格式的快照,后半部分是AOF日志,兼顾了恢复速度和数据安全性。这也是目前官方推荐的持久化方案。