Redis 通过 RDB 方式进行数据备份与还原的方法
Intro
有的时候我们需要对Redis的数据进行迁移,今天介绍一下通过RDB(快照)文件进行Redis数据的备份和还原
Redis持久化
Redis的数据持久化有两种机制,一种是RDB(RedisDatabase),一种是AOF(AppendOnlyFile)
Redis提供了不同级别的持久化方式:
- RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储.
- AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大.
- 如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式.
- 你也可以同时开启两种持久化方式,在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整.
RDB的优点
- RDB是一个非常紧凑的文件,它保存了某个时间点得数据集,非常适用于数据集的备份,比如你可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集.
- RDB是一个紧凑的单一文件,很方便传送到另一个远端数据中心或者亚马逊的S3(可能加密),非常适用于灾难恢复.
- RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.
- 与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.
RDB的缺点
- 如果你希望在redis意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么RDB不适合你.虽然你可以配置不同的save时间点(例如每隔5分钟并且对数据集有100个写的操作),是Redis要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔5分钟或者更久做一次完整的保存,万一在Redis意外宕机,你可能会丢失几分钟的数据.
- RDB需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求.如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒,AOF也需要fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度.
AOF优点
- 使用AOF会让你的Redis更加耐久:你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据.
- AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题.
- Redis可以在AOF文件体积变得过大时,自动地在后台对AOF进行重写:重写后的新AOF文件包含了恢复当前数据集所需的最小命令集合。整个重写操作是绝对安全的,因为Redis在创建新AOF文件的过程中,会继续将命令追加到现有的AOF文件里面,即使重写过程中发生停机,现有的AOF文件也不会丢失。而一旦新AOF文件创建完毕,Redis就会从旧AOF文件切换到新AOF文件,并开始对新AOF文件进行追加操作。
- AOF文件有序地保存了对数据库执行的所有写入操作,这些写入操作以Redis协议的格式保存,因此AOF文件的内容非常容易被人读懂,对文件进行分析(parse)也很轻松。导出(export)AOF文件也非常简单:举个例子,如果你不小心执行了FLUSHALL命令,但只要AOF文件未被重写,那么只要停止服务器,移除AOF文件末尾的FLUSHALL命令,并重启Redis,就可以将数据集恢复到FLUSHALL执行之前的状态。
AOF缺点
- 对于相同的数据集来说,AOF文件的体积通常要大于RDB文件的体积。
- 根据所使用的fsync策略,AOF的速度可能会慢于RDB。在一般情况下,每秒fsync的性能依然非常高,而关闭fsync可以让AOF的速度和RDB一样快,即使在高负荷之下也是如此。不过在处理巨大的写入载入时,RDB可以提供更有保证的最大延迟时间(latency)。
废话不多说直接看下面的示例吧,通过docker运行一个redis实例,并设置一些数据,然后导出RDB文件,再运行一个redis实例通过RDB文件还原数据
备份
通过dockerrun-d--nameredis-test-1redis:alpine命令来创建一个redis实例,接着SET一个key保存到我们的redis,使用命令SEThelloworld写入测试数据,你也可以写入别的自己想写的数据,接着可以使用keys*来验证数据是否写入成功
测试数据写入成功后使用SAVE命令来创建RDB文件,命令执行成功后我们可以在/data目录下看到会有一个dump.rdb文件,这就是我们想要的RDB文件,通过dockercp命令可以把这个文件拷贝到host目录下
还原
通过上面RDB文件我们可以在redis启动的时候还原RDB文件中的数据,只需要在Redis启动前把RDB文件放在redis的data目录下就可以了。
执行dockerrun--rm--nameredis-test-2-v${pwd}/data:/dataredis:alpine
这个命令我是在powershell上执行的,如果执行在Linux上执行需要把${pwd}换成$(pwd)来表示当前目录
可以看到上面的日志里有LoadingRDB...就是在加载RDB文件中的数据
我们再来验证一下RDB文件里的数据是否真的加载到了新的redis实例中,先来验证一下data目录是否正常挂载了,执行dockerexec-itredis-test-2sh来进入到redis实例容器中,ls查看data目录中的文件看是否有我们期望的RDB文件,接着进入redis-cli来验证数据是否存在
使用keys*来列出来所有的key信息,可以看到有我们在上一个redis里写入的测试数据了,再来使用GEThello来验证数据是否正确,至此我们的数据就还原到新的redis实例中了~~
More
当Redis需要保存dump.rdb文件时,服务器执行以下操作:
- Redis调用forks.同时拥有父进程和子进程。
- 子进程将数据集写入到一个临时RDB文件中。
- 当子进程完成对新RDB文件的写入时,Redis用新RDB文件替换原来的RDB文件,并删除旧的RDB文件。
这种工作方式使得Redis可以从写时复制(copy-on-write)机制中获益。
如果redis被访问的比较频繁,可以使用BGSAVE代替SAVE来异步创建RDB备份
如果redis不是使用docker来使用的,/data目录可以在redis-cli中使用CONFIGGETdir来获取保存rdb文件的目录,默认保存的RDB文件名称是dump.rdb,如果有修改过,可以通过CONFIGGETdbfilename来获取当前使用的文件名
References
https://redis.io/topics/persistence
http://redis.cn/topics/persistence.html
到此这篇关于Redis通过RDB方式进行数据备份与还原的文章就介绍到这了,更多相关Redis数据备份与还原内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!