📚背景介绍
✒️ Redis数据恢复的介绍
通常情况下redis的数据全部存储在内存中,数据库一旦故障发生重启数据会全部丢失,持久化功能在于能够有效地避免因进程退出造成的数据丢失问题,在下次重启时利用之前持久化的文件即可实现数据恢复。
✒️ Redis高可用的功能基础
即使是在redis cluster或者redis sentinel模式下主从同步数据的恢复仍然需要一段时间。
✒️ Redis实际场景的分析
开启Redis持久化之后,数据将存放到磁盘中,数据库执行增量同步的时间要远小于全量同步。在生产环境下故障的数据恢复有着非常重要的作用!
📚前提概要
Redis是出了名的速度快,那是因为在内存中进行数据存储和操作;如果仅仅是在内存中进行数据存储,那就会导致以下问题:
-
数据随进程退出而消失:当服务器断电或Redis Server进程退出时,内存肯定随之释放,最后数据也会丢失;
- 有些小伙伴认为只是作为缓存,数据没有了,重新从数据库中读取放在里面即可,试想,如果是高并发场景,数据库岂不是压力很大;
-
重要数据无法恢复:数据丢失之后无法进行恢复,对于一些重要的数据,只是存在Redis中,而没有存在关系型数据库,如果数据丢失便不可恢复;比如刷礼品排行榜,如果数据丢失,用户肯定不愿意的;
- 对于Redis持久化在工作中和面试过程中是一个很重要的技术点,必用必考,接下来详细说说Redis持久化;
📚 基本介绍
✒️ Redis持久化有两种方案
-
RDB(Redis DataBase)是一种快照式的二进制数据存储,它会周期性的保存当前时间点Redis所有的数据到磁盘中。
-
AOF(Append Of FIle)是一种追加式的存储方式,会实时的记录Redis的写操作到磁盘中。
✒️ Redis持久化机制实现
- Redis是基于内存进行操作运算,如果不持久化数据再重启服务时会导致数据丢失。
- 开启Redis持久化功能后,数据会保存到磁盘中。当redis重启后,可以从磁盘中恢复数据。
✒️ RDB快照(snapshot)
✒️ RDB持久化方式
RDB持久化把当前进程数据生成快照(.rdb)文件保存到硬盘的过程,有手动触发和自动触发。
✒️ RDB手动触发
手动触发有save和bgsave两命令。
✒️ save命令
-
该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。
-
执行完成时候如果存在老的RDB文件,就把新的替代掉旧的。我们的客户端可能都是几万或者是几十万,这种方式显然不可取。
在执行redis-cli shutdown关闭redis服务时,如果没有开启AOF持久化,自动执行save。
✒️ bgsave命令
-
Redis主进程fork一个子进程来创建临时RDB存储文件,创建文件完成后对这个临时文件rename替换原先的RDB文件。
-
RDB文件是一个单文件很适合数据的容灾备份与恢复,通过RDB文件恢复数据库耗时较短,通常1G的快照文件载入内存只需20s左右。
✒️ bgsave命令和save命令
命令名称 | save | bgsave |
---|---|---|
IO类型 | 同步 | 异步 |
是否阻塞 | 是 | 否 |
复杂度 | O(n) | O(n) |
优点 | 不会耗费额外内存 | 不阻塞客户端访问 |
缺点 | 阻塞客户端访问 | 耗费多余客户端 |
在指定时间间隔内将内存中的数据库记录集dump到磁盘上,RDB是默认的持久化方式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。
✒️ RDB自动触发
自动触发是由我们的配置文件来完成的,自动触发bgsave。
✒️ 配置方法
-
在redis.conf文件中配置N 秒内数据集至少有 M 个改动时自动触发一次RDB持久化,Redis会将数据集的快照dump到dump.rdb文件中。
-
我们也可以通过配置文件来修改Redis服务器dump快照的频率,在打开6379.conf文件之后,我们搜索save,可以看到下面的配置信息:
✒️ 60秒内至少有10000个键被修改
- save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。
- save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。
- save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,dump内存快照。
关闭RDB方式持久化只需要将所有save保存策略注释掉即可
✒️ RDB持久化命令
- 命令:config set dir /usr/local //设置rdb文件保存路径
- 备份:bgsave //将dump.rdb保存到usr/local下
- 恢复:将dump.rdb放到redis安装目录与redis.conf同级目录,重启redis即可
save命令是同步命令,bgsave命令是异步命令,会从redis主进程fork出一个子进程去处理,每次命令执行后会新生成一个rdb文件并覆盖原来的文件。
✒️ 修改配置
-
rdbcompression yes:rdb文件压缩是否开启
-
dbfilename dump.rdb:rdb文件名称定义
✒️ RDB的优缺点
✒️ 优点
- (恢复速度快,适合大数量恢复机制)RDB保存的是某一个时间点的内存快照,非常适合灾难恢复。在恢复大数据集时速度快,1G的RDB数据恢复耗时大概20s,比AOF要快的多
✒️ 缺点
-
(间隔时间大并且丢失数据较为多)RDB通过触发某个时间点条件生成快照文件,如果5分钟保存一次的话,一旦发生故障会丢失好几分钟的数据,配置不同的保存点让RDB至少可以保存5分钟的数据。因此,如果Redis由于任何原因没有正确关闭而停止工作,你应该做好好丢失最近几分钟的数据
-
(CPU资源占用过大、内存资源占用过多)fork子进程消耗内存和CPU,RDB经常需要 fork() 才能使用子进程在磁盘上持久化。如果数据集很大,fork()可能很耗时,如果数据集非常大,CPU性能不好,可能会导致Redis停止为客户机服务几毫秒甚至一秒钟。
✒️ AOF(append-only file)
由于RDB快照方式的缺点,如果redis由于某些原因导致机器故障时,则会丢失最近几分钟写入的数据,而AOF持久化方式,则通过追加的方式将操作命令添加到appendonly.aof文件中,存储的文件是RESP协议指令文件。
✒️ 配置方法
-
appendonly yes # 开启AOF持久化,(默认不开启,为no)
-
appendfilename “appendonly.aof”:默认文件名
配置好后,redis每次修改操作的命令会追加到AOF末尾,当redis重启后会重新执行AOF里的命令达到重建缓存数据集的目的,配置刷命令的频率。
-
appendfsync always :每次有新命令追加到AOF文件时就执行一次fsync,非常慢但最安全。服务器在每执行一个事件就把AOF缓冲区的内容强制性的写入硬盘上的AOF文件里,保证了数据持久化的完整性,效率是最慢的但最安全的;
-
appendfsync everysec # 服务端每隔一秒才会进行一次文件同步把内存缓冲区里的AOF缓存数据真正写入AOF文件里,兼顾了效率和完整性,极端情况服务器宕机只会丢失一秒内对Redis数据库的写操作;默认方式
-
appendfsync no # 从不fsync,交由操作系统处理,速度快,表示默认系统的缓存区写入磁盘的机制,不做程序强制,数据安全性和完整性差一些。
-
bgrewriteaof:后台运作重写机制
-
auto-aof-rewrite-min-size 64mb # aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就很快,重写的意义不大
-
auto-aof-rewrite-percentage 100 # aof文件自上一次重写后文件大小增长了100%,则再次触发重写执行bgrewriteaof命令可以手动重写aof文件,AOF重写redis会fork出一个子进程去做,不会对redis正常命令处理有太多影响。
redis启动时如果既有rdb文件又有aof文件则优先选择aof文件恢复数据,因为aof一般来说数据更全一点。
-
全量同步(RDB):每天定时(避开高峰期)或者采用一个周期实现将数据拷贝到一个地方。
-
增量同步(AOF):比如采用对行为的操作实现对数据的同步。
-
增量同步比全量同步更加消耗服务器的内存,但是能够更加的保证数据的同步。
📚 AOF的优缺点
✒️ 优点
AOF是通过保存Redis写操作的命令来实现持久化,使用AOF来持久化,Redis数据的安全性将大幅提高,异常宕机情况下最多丢失1s的数据。AOF文件记录了redis的写操作,格式清晰,易于理解和修改,利于数据的重建。
AOF日志是一个只附加的日志,因此如果断电,就不会出现查找或损坏问题。即使日志由于某种原因(磁盘已满或其他原因)以半写的命令结束,redis check aof工具也可以轻松地修复它。
当AOF太大时,Redis能够在后台自动重写AOF。重写是完全安全的,因为当Redis继续附加到旧文件时,一个全新的文件会生成,只需创建当前数据集所需的最少操作集,一旦第二个文件就绪,Redis就会切换这两个文件并开始附加到新文件中。
AOF以易于理解和解析的格式包含所有操作的日志。你甚至可以轻松导出AOF文件。
✒️ 缺点
-
AOF文件通常比相同数据集的等效RDB文件大。
-
根据具体的fsync策略,AOF可能比RDB慢。
使用建议
Redis默认开启了持久化功能,而且是全量RDB的,缺点是服务器宕机后可能会造成数据丢失。
建议最好还是搭配使用aof的everysec,既能够保证数据的同步,效率也还可以,但是会存在丢失一秒数据的可能性,就算丢失也关系不大,因为数据库中已经存在了数据。
混合持久化
如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的AOF文件会原子覆盖掉原来的AOF文件。
开启混合持久化命令
aof-use-rdb-preamble yes # 开启混合持久化
appendonly.aof文件中同时保存着RDB和AOF两种格式的数据