Redis系列:RDB内存快照提供持久化能力
1 介绍
从上一篇的 《深刻理解高性能Redis的本质》 中可以知道, 我们经常在数据库层上加一层缓存(如Redis),来保证数据的访问效率。
这样性能确实也有了大幅度的提升,因为从内存中取数远比从磁盘中快的多,但是本身Redis也是一层服务,也存在宕机、故障的可能性。
一旦服务挂起,可能生产的后果包括如下几方面:
1. Redis的数据是存在内存中的,所以一旦挂起,内存中的数据会全部丢失。
2. I/O从内存层级迁移到磁盘层级,性能极速下降。
3. 原本访问缓存的请求会透过缓存层直接投向数据库,给数据库带来极大的压力,甚至导致雪崩。
所以,缓存层崩溃产生的后果是灾难的。为了避免宕机和宕机后的数据丢失, 为了保证数据的快速恢复,Redis提供了两个持久化数据的能力,RDB Snapshot 和 AOF(Append Only FIle)日志。本章我们先来看看RDB快照的使用。
2 什么是RDB内存快照
大规模高并发的分布式场景,经常会遇到问题就是Redis挂起,导致访问失败,而所有的请求透过缓存层投向数据库,给数据库造成极大的压力,甚至雪崩。
而Redis的数据是存储在高速缓存中,即使我们重启并且恢复使用,缓存池依旧是空的,因为内存被释放了。
重新建立缓存的过程,对数据库也是一个暴击的过程,很可能会导致整个系统调用链的雪崩。参考我的这篇《架构与思维:一次缓存雪崩的灾难复盘》
所以更为稳妥的办法是持久化到磁盘中,这样哪怕重启数据也不会消失。但是如果每次数据的变化(增、删、改)都要写内存并同时写磁盘,这样成本太高,内存+磁盘的持续数据同步,会让 Redis 性能大大降低。而且还要保证原子性操作,避免内存和磁盘的数据不一致。
2.1 使用内存快照
为了避免实时写入高频操作磁盘带来的负面效应。Redis提供了内存快照策略。
工作原理是,Redis在指定的时间间隔内,将内存中的数据集快照定格下来,写入磁盘,并存储在副本文件中。当Redis重启时,这些快照文件会被自动读取并恢复到内存中。打游戏的同学可以想象存盘,下一次恢复游戏,可以从存盘的地方读取游戏直接开始。

如上图,将指定时间的Redis缓存数据进行快照。当发生故障的时候,直接从最接近的时间点进行数据恢复(即21:10的故障按照21点的RDB快照进行恢复),直接将 RDB 文件读入内存完成恢复。
2.2 生成RDB策略
在Redis的RDB持久化方案中,提供了两种模式来生成RDS文件,分别是 SAVE 和 BGSAVE。虽然都是用于创建内存快照并保存到磁盘的命令,但两者在执行方式和影响上有明显的区别。
SAVE命令会阻塞当前Redis服务器进程,直到RDB文件创建完毕。
在执行SAVE命令期间,Redis不能处理其他命令,阻塞主进程,这会导致服务器无法响应其他请求,直到RDB过程完成为止。因此,当数据量较大时,使用SAVE命令可能会对Redis的性能产生较大影响。
BGSAVE命令则会在后台异步进行快照操作,同时Redis还可以继续处理客户端的请求。
BGSAVE命令通过fork一个子进程来完成持久化任务,这样主进程就不会被阻塞,从而保证了Redis的高可用性。但是,由于需要fork一个子进程,BGSAVE命令可能会消耗更多的内存资源。
2.2.1 SAVE模式
save模式是主进程执行,非常不建议使用主进程执行的方式,在笔者的 《深刻理解高性能Redis的本质》 一文中,
我们介绍了它的主操作都是在单线程模型上完成的。所以 RDB 文件生成会影响主线程的网络I/O和键值对读写,导致客户端正常操作被阻塞,所以应该尽量避免。
2.2.2 BGSAVE模式
bgsave是后台异步执行,通过调用glibc函数创建一个子进程专门用于写入RDB文件,从而避免了主线程的阻塞。当执行BGSAVE命令时,Redis会继续处理其他客户端请求(比如Get、Set等),而子进程会在后台完成RDB文件的生成。这是Redis RDB文件生成的默认配置,也是推荐的方式。

上图执行流程如下:
- 执行bgsave命令,Redis主进程判断当前是否存在正在执行的RDB/AOF子进程,若果存在则bgsave命令直接返回。
- 主进程执行fork操作创建子进程,fork操作过程中父进程会阻塞(创建子进程),通过
info stats命令查看latest_fork_usec选项,可以获取最近一个fork操作的耗时,单位为微秒 - 父进程fork完成后,bgsave命令返回
Background saving started信息,之后的操作都是异步的了,不再阻塞主进程,Client的Get、Set等操作依然可以执行。 - fork子进程的做法是通过调用glibc函数进行创建的,这步骤跟第2点对齐,都是会有短暂的阻塞。
- 子进程创建RDB文件,在主进程内存中生成临时快照文件,完成后对原有文件进行原子替换。执行
lastsave命令可以获取最后一次生成RDB的时间,对应rdb_last_save_time选项。 - 子进程发送信号给主进程表示完成,主进程接受到信息并更新统计记录。
以上整个过程保证了快照的完整性,也允许主进程同时对数据进行修改,避免了对正常业务的影响。
2.2.3 避免过频的全量Snapshot
虽然说Redis 使用 bgsave 函数 fork 子进程在后台完成内存中的数据做快照,并不阻塞父进程继续处理客户端的操作。
但过频执行全量数据快照,依然会导致严重的性能开销,主要如下:
- 频繁生成 RDB 文件写入磁盘,磁盘空间占用大,IO压力大,也会降低效率。
- fork 出来的 bgsave 子进程因为共享主线程的资源,一定程度上会影响主线程的运行性能。
2.3 总结
快照的恢复速度快,但是生成 RDB 文件的频率需要把握一个度,频率过低快照间隔数据较大,丢失的数据就会比较多;频率太快,又会消耗额外开销,降低Redis性能。
RDB内存快照优缺点如下:
优点:
- RDB以一种二进制格式+数据压缩的方式写磁盘,文件轻量。
- 数据恢复速度快,用于灾难恢复的场景,加载 RDB 恢复数据远快于 AOF 方式。
缺点:
- 无法做到实时持久化,每次都要创建子进程, 频繁操作成本过高
- 保存后的二进制文件, 存在老版本不兼容新版本 rdb 文件的问题
- 数据恢复不完全,快照时间点和故障时间点之间必然有时间差、数据差
Redis系列:RDB内存快照提供持久化能力的更多相关文章
- Redis系列之-—内存淘汰策略(笔记)
一.Redis ---获取设置的Redis能使用的最大内存大小 []> config get maxmemory ) "maxmemory" ) " --获取当前内 ...
- Redis的两种持久化方式-快照持久化(RDB)和AOF持久化
Redis为了内部数据的安全考虑,会把本身的数据以文件形式保存到硬盘中一份,在服务器重启之后会自动把硬盘的数据恢复到内存(redis)的里边,数据保存到硬盘的过程就称为“持久化”效果. redis有两 ...
- Redis系列2:数据持久化提高可用性
1 介绍 从上一篇的 <深刻理解高性能Redis的本质> 中可以知道, 我们经常在数据库层上加一层缓存(如Redis),来保证数据的访问效率. 这样性能确实也有了大幅度的提升,但是本身Re ...
- linux之 redis 的rdb 转 aof 及主从复
redis持久化RDB基于快照的持久化通过save命令,强制持久化 在redis.conf中dbfilename dbmp.rdbsave 900 1save 300 10save 60 10 ...
- Redis基础篇(四)持久化:内存快照(RDB)
AOF好处是每次执行只需要记录操作命令,记录量不大.但在故障恢复时,需要逐一执行AOF的操作命令,如果日志很大,恢复就很慢. 今天学习另一种持久化方式:内存快照.内存快照,是Redis某一时刻的状态, ...
- Redis持久化——内存快照(RDB)
最新:Redis持久化--如何选择合适的持久化方式 最新:Redis持久化--AOF日志 最新:Redis持久化--内存快照(RDB) 一文回顾Redis五大对象(数据类型) Redis对象--有序集 ...
- Redis系列(三):Redis的持久化机制(RDB、AOF)
本篇博客是Redis系列的第3篇,主要讲解下Redis的2种持久化机制:RDB和AOF. 本系列的前2篇可以点击以下链接查看: Redis系列(一):Redis简介及环境安装. Redis系列(二): ...
- redis 系列16 持久化 RDB
一.概述 Redis是内存数据库,一旦服务器进程退出,服务器中的数据库内存数据状态也会消失.为了解决这个问题,Redis提供了RDB 持久化功能,这个功能可以将redis在内存中的数据库状态保存到磁盘 ...
- redis系列:RDB持久化与AOF持久化
前言 什么是持久化? 持久化(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘).持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中.XML数 ...
- redis 实战操作RDB和AOF快照持久化
前言:redis是我们常用的缓存方式,今天就来介绍下两种持久化的方式吧,先科普概念,再实战操作 一.RDB Redis将某一时刻的快照(备份的数据库数据)保存成一种称为RDB格式的文件中,这种格式是经 ...
随机推荐
- 从零开始配置vim(20)——模糊查询
在讲解vim的基础功能的时候,介绍过了vim的各种查询技巧,在同一个文件中进行搜索的话,那些技巧很有用.在多个文件中我们介绍了使用vim自带的 :grep命令进行搜索,使用quickfix 列表进行跳 ...
- python快速入门【四】-----各类函数创建
python入门合集: python快速入门[一]-----基础语法 python快速入门[二]----常见的数据结构 python快速入门[三]-----For 循环.While 循环 python ...
- 19.7 Boost Asio 传输序列化数据
序列化和反序列化是指将数据结构或对象转换为一组字节,以便在需要时可以将其存储在磁盘上或通过网络传输,并且可以在需要时重新创建原始对象或数据结构. 序列化是将内存中的对象转换为字节的过程.在序列化期间, ...
- grafana+prometheus+loki的使用
grafana官网:https://grafana.com/zh-cn/grafana/ grafana下载:https://grafana.com/grafana/download?pg=graf& ...
- 予力八六三软件应用现代化,提升DevSecOps效能,探索交付之路
本文分享自华为云社区<予力八六三软件应用现代化,提升DevSecOps效能,探索全球交付之路>,作者: HuaweiCloudDeveloper. 来源:<华为云DTSE>期刊 ...
- uni-app+vue3会遇到哪些问题
已经用 uni-app+vue3+ts 开发了一段时间,记录一下日常遇见的问题和解决办法 uni-app 中的单端代码 uni-app 是支持多端,如果你想让你的代码,只在部分平台使用,那么就需要用的 ...
- MySQL执行函数时报错:Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and (utf8mb4_0900_ai_ci,IMPLICIT) for operation 'find_in_set'
执行函数时报错: Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and (utf8mb4_0900_ai_ci,IMPLICIT) f ...
- 解决highlightjs中纯文本被解析成HTML无法展示的问题,记一次工作中bug修复的思考
壹 ❀ 引 在本周迭代bug修复工作中,遇到了两个比较头疼的bug(同一个客户所提),bug问题描述也很奇怪,客户表示产品的富文本编辑器里的代码块功能,在纯文本语言模式下贴特定代码进去有的看不见,有的 ...
- MFC-ODBC API动态连接配置数据库
一.ODBC管理器介绍 在Window中,ODBC数据远管理器有6个标签:用户DSN.系统DSN.文件DSN.驱动程序.跟踪.连接池,通常情况下,使用用户DSN或者系统DSN,这里主要了解用户DSN和 ...
- NC16810 [NOIP1999]拦截导弹
题目链接 题目 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达 ...