RDB持久化

一、生成 RDB 的方式

两个命令可以生成 RDB 文件:save 和 bgsave
save:在主线程中执行,会导致阻塞,线上环境不建议使用
bgsave:创建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞,这也是 Redis RDB 文件生成的默认配置。
bgsave 为了保证快照完整性,这期间只能处理读操作,Redis 借助操作系统提供的写时复制技术(Copy-On-Write,COW),在执行快照的同时,能正常处理写请求。
写时复制技术:如果主线程要修改一块数据,那么,这块数据就会被复制一份,生成该数据的副本。
然后 bgsave 子进程会把这个副本写入 RDB 文件,而这个过程中,主线程仍然可以直接修改原来的数据。
这里解释一下几个跟 RDB 相关的参数:
rdb_changes_since_last_save:自上次 RDB 后,Redis 数据的改动条数
rdb_bgsave_in_progress:bgsave 是否在进行中,0 否,1 是
rdb_last_save_time:上次 bgsave 的时间戳
rdb_last_bgsave_status:上次 bgsave 的状态
rdb_last_bgsave_time_sec:上次 bgsave 的持续时间
rdb_current_bgsave_time_sec:正在执行的 bgsave 耗时,如果没有正在执行的,则为 -1
rdb_last_cow_size:上次 RDB 过程中父进程与子进程相比执行了多少修改
根据 rdb_bgsave_in_progress 这一项为 0,可以判断在执行 info Persistence 命令时,bgsave 已经执行完成了。除了通过命令的方式触发 RDB 持久化之外,Redis 内部还有自动触发 RDB 的机制。
比如以下场景:
配置文件中增加了类似 "save m n" 的配置,表示 m 秒内有 n 次修改则自动触发 bgsave。
新建立 Redis 主从复制时,主节点会执行一次 bgsave 保存 RDB 文件到本地,然后发送给从节点。
执行 shutdown 时,如果没有开启 AOF 则自动执行 bgsave

二、频繁执行全量快照的影响

如果频繁执行全量快照,会带来两方面的开销:
频繁将全量数据写入磁盘,会给磁盘带来很大压力,可能出现前面的没做完,后面的又开始了。导致恶性循环。
bgsave 子进程需要通过 fork 操作从主线程创建出来,虽然,子进程在创建后不在会阻塞主线程,但是,fork这个创建过程本身会阻塞主线程,而且主线程内存越大,阻塞时间越长。

三、RDB 所在分区磁盘满了怎么办

当遇到 RDB 所在分区磁盘满了,可以临时修改 RDB 路径,操作如下:
config set dir /
// 表示还有空间的其他分区下的文件夹

四、开启 RDB 压缩

Redis 支持对 RDB 进行压缩,参数为 rdbcompression,设置为 yes 表示开启(默认开启的)。压缩不但可以节省磁盘空间,在创建主从时,也能更快的将全量备份传给从实例,因此建议开启压缩功能。

五、RDB 文件损坏检测

当发现 Reids RDB 文件损坏时,可以使用 redis-check-rdb 进行检测
redis-check-rdb dump.rdb

六、单机多实例的 RDB 备份

有些情况,我们会在单台服务器上部署多个 Redis 实例,但是使用配置文件中增加 save 的方式又怕几个实例 RDB 时间冲突,从而影响落盘速度。这种情况,可以使用脚本结合定时任务触发 bgsave 进行 RDB 备份。
这样,同机器不同实例的 RDB 备份时间可以自定义错开,防止 IO 跑满带来的问题。

七、备份建议

那么 Redis 究竟怎么备份更好呢?RDB 尽管恢复会快很多,但是可靠性比 AOF 低,但是如果只使用 AOF,又会存在恢复慢的问题,因此,Redis 4.0 提出了混合使用 AOF 日志和内存快照的方法。因此对于 Redis 的备份,建议如下:
数据不能丢失时,内存快照和 AOF 的混合使用是一个很好的选择
如果允许分钟级别的数据丢失,可以只使用 RDB
如果只用 AOF ,优先使用 everysec 的配置选项,因为其介于可靠性和性能之间。
当然,如果有从实例,也优先考虑在从实例上进行备份。
posted @ 2025-06-17 23:27  屠魔的少年  阅读(10)  评论(0)    收藏  举报