文章目录
什么是Redis持久化?
持久化就是把内存的数据写到磁盘上,防止服务器宕机了内存数据丢失
Redis 是内存型数据库,为了之后重用数据(比如重启机器、机器故障之后回复数据),或者是为了防止系统故障而将数据备份到一个远程位置,需要将内存中的数据持久化到硬盘上。
Redis 提供了RDB(默认)
和AOF
两种持久化方式。默认是只开启RDB,当Redis重启时,它会优先使用AOF文件来还原数据集。
RDB 持久化(快照持久化)
- rdb是Redis DataBase缩写:功能核心函数
rdbSave
(生成RDB文件)和rdbLoad
(从文件加载两个函数)。 - RDB 持久化:将某个时间点的所有数据都存放到硬盘上。通过fork一个子进程来进行操作,不会阻塞主进程。
- 快照是默认的持久化方式,这种方式是将内存的数据以快照的方式写入到二进制文件中,默认的文件名dump.rdb。
- 优点:快照保存数据极快,还原数据极快,适用于灾难备份。
- 缺点:小内存机器不适合使用,RDB机制符合要求就会照快照。
可以将快照复制到其它服务器从而创建具有相同数据的服务器副本。如果系统发生故障,将会丢失最后一次创建快照之后的数据。如果数据量很大,保存快照的时间会很长。
快照持久化是Redis默认采用的持久化方式,在redis.conf配置文件中默认有此下配置:
#在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
save 900 1
#在300秒(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
save 300 10
#在60秒(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
save 60 10000
根据配置,快照将被写入dbfilename
选项指定的文件里面,并存储在dir
选项指定的路径上面。如果在新的快照文件创建完毕之前,Redis、系统或者硬件这三者中的任意一个崩溃了,那么Redis将丢失最近一次创建快照写入的所有数据。
举个例子:假设Redis的上一个快照是2:35开始创建的,并且已经创建成功。下午3:06时,Redis又开始创建新的快照,并且在下午3:08快照创建完毕之前,有35个键进行了更新。如果在下午3:06到3:08期间,系统发生了崩溃,导致Redis无法完成新快照的创建工作,那么Redis将丢失下午2:35之后写入的所有数据。另一方面,如果系统恰好在新的快照文件创建完毕之后崩溃,那么Redis将丢失35个键的更新数据。
创建快照的办法有如下几种:
-
BGSAVE命令 :客户端向Redis发送 BGSAVE命令 来创建一个快照。对于支持BGSAVE命令的平台来说(基本上所有平台支持,除了Windows平台),Redis会调用
fork
来创建一个子进程,然后子进程负责将快照写入硬盘,而父进程则继续处理命令请求。 -
如果要查看BGSAVE命令的结果,可以继续执行lastsave命令,该命令返回的是一个时间戳,表示最近一次把内存数据存入快照文件的时间,如果该时间和BGSAVE命令的运行时间能对应上,则能说明BGSAVE命令执行成功。
-
SAVE命令 :客户端还可以向Redis发送 SAVE命令 来创建一个快照,接到SAVE命令的Redis服务器在快照创建完毕之前不会再响应任何其他命令。SAVE命令不常用,我们通常只会在没有足够内存去执行BGSAVE命令的情况下,又或者即使等待持久化操作执行完毕也无所谓的情况下,才会使用这个命令。
-
save选项 :如果用户设置了save选项(一般会默认设置),比如 save 60 10000,那么从Redis最近一次创建快照之后开始算起,当“60秒之内有10000次写入”这个条件被满足时,Redis就会自动触发BGSAVE命令。
-
SHUTDOWN命令 :当Redis通过SHUTDOWN命令接收到关闭服务器的请求时,或者接收到标准TERM信号时,会执行一个SAVE命令,阻塞所有客户端,不再执行客户端发送的任何命令,并在SAVE命令执行完毕之后关闭服务器。
-
一个Redis服务器连接到另一个Redis服务器:当一个Redis服务器连接到另一个Redis服务器,并向对方发送SYNC命令来开始一次复制操作的时候,如果主服务器目前没有执行BGSAVE操作,或者主服务器并非刚刚执行完BGSAVE操作,那么主服务器就会执行BGSAVE命令
如果系统真的发生崩溃,用户将丢失最近一次生成快照之后更改的所有数据。因此,快照持久化只适用于即使丢失一部分数据也不会造成一些大问题的应用程序。不能接受这个缺点的话,可以考虑AOF持久化。
怎么使用RDB文件恢复数据
将备份文件dump.rdb
移动到redis安装目录并重启服务器即可。
可以使用命令获取安装目录config get dir
127.0.0.1:6379> config get dir
1) "dir"
2) "D:\\install\\redis\\Redis-x64-3.2.100"
AOF 持久化
由于快照方式是在一定间隔时间做一次的,如果redis意外down掉的话,就会丢失最后一次快照后的所有数据,如果应用要求不能丢失任何修改的化,可以采用aof持久化方式
AOF 持久化:将写命令添加到 AOF 文件(Append Only File
)的末尾。aof比快照方式由更好的持久性,是由于在使用aop持久化方式时,redis将每一个收到的写命令都通过write函数追加文件中(默认是appendonly.aof),当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容
与快照持久化相比,AOF持久化 的实时性更好,因此已成为主流的持久化方案。默认情况下Redis没有开启AOF(append only file)方式的持久化,可以通过appendonly参数开启:
appendonly yes
开启AOF持久化后每执行一条会更改Redis中的数据的命令,Redis就会将该命令写入硬盘中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的,默认的文件名是appendonly.aof
。当然也可以使用appendfilename自己定义文件名称。
使用 AOF 持久化需要设置同步选项,从而确定写命令同步到磁盘文件上的时机。这是因为对文件进行写入并不会马上将内容同步到磁盘上,而是先存储到缓冲区,然后由操作系统决定什么时候同步到磁盘。在Redis的配置文件中存在三种同步方式
选项 | 同步频率 |
---|---|
always | 每个写命令都同步,这样会严重降低Redis的速度 |
everysec | 每秒同步一次 |
no | 让操作系统来决定何时同步 |
appendfsync always
可以实现将数据丢失减到最少,不过这种方式需要对硬盘进行大量的写入而且每次只写入一个命令,十分影响Redis的速度。另外使用固态硬盘的用户谨慎使用appendfsync always选项,因为这会明显降低固态硬盘的使用寿命。appendfsync everysec
为了兼顾数据和写入性能,用户可以考虑appendfsync everysec
选项 ,让Redis每秒同步一次AOF文件,Redis性能几乎没受到任何影响。而且这样即使出现系统崩溃,用户最多只会丢失一秒之内产生的数据。当硬盘忙于执行写入操作的时候,Redis还会优雅的放慢自己的速度以便适应硬盘的最大写入速度。appendfsync no
选项一般不推荐,这种方案会使Redis丢失不定量的数据而且如果用户的硬盘处理写入操作的速度不够的话,那么当缓冲区被等待写入的数据填满时,Redis的写入操作将被阻塞,这会导致Redis的请求速度变慢。
随着服务器写请求的增多,AOF 文件会越来越大。Redis 提供了一种将 AOF
重写的特性,能够去除 AOF 文件中的冗余写命令。
虽然AOF持久化非常灵活地提供了多种不同的选项来满足不同应用程序对数据安全的不同要求,但AOF持久化也有缺陷——AOF文件的体积太大。
怎么使用AOF文件恢复数据
正常启动
将备份文件appendonly.aof
移动到redis安装目录并重启服务器即可。
可以使用命令获取安装目录config get dir
127.0.0.1:6379> config get dir
1) "dir"
2) "D:\\install\\redis\\Redis-x64-3.2.100"
异常启动
使用redis-check-aof 来修复
cp appendonly.aof appendonly.aof.bak#备份文件
redis-check-aof --fix appendonly.aof #修复文件
重写/压缩AOF
AOF虽然在某个角度可以将数据丢失降低到最小而且对性能影响也很小,但是极端的情况下,体积不断增大的AOF文件很可能会用完硬盘空间。另外,如果AOF体积过大,那么还原操作执行时间就可能会非常长。
为了解决AOF体积过大的问题,用户可以向Redis
发送 BGREWRITEAOF
命令 ,这个命令会通过移除AOF文件中的冗余命令来重写(rewrite)AOF文件来减小AOF文件的体积。BGREWRITEAOF命令和BGSAVE创建快照原理十分相似,所以AOF文件重写也需要用到子进程,这样会导致性能问题和内存占用问题,和快照持久化一样。更糟糕的是,如果不加以控制的话,AOF文件的体积可能会比快照文件大好几倍。
文件重写流程:
和快照持久化可以通过设置save选项来自动执行BGSAVE一样,AOF持久化设置以下参数
auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size
选项自动执行BGREWRITEAOF命令。举例:假设用户对Redis设置了如下配置选项并且启用了AOF持久化。那么当AOF文件体积大于64mb,并且AOF的体积比上一次重写之后的体积大了至少一倍(100%)的时候,Redis将执行BGREWRITEAOF命令。
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
无论是AOF持久化还是快照持久化,将数据持久化到硬盘上都是非常有必要的,但除了进行持久化外,用户还必须对持久化得到的文件进行备份(最好是备份到不同的地方),这样才能尽量避免数据丢失事故发生。如果条件允许的话,最好能将快照文件和重新重写的AOF文件备份到不同的服务器上面。
随着负载量的上升,或者数据的完整性变得越来越重要时,用户可能需要使用到复制特性。
Redis 4.0 对持久化机制的优化
Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,可以通过配置项 aof-use-rdb-preamble
开启)
如果把混合持久化打开,AOF 重写的时候就直接把 RDB 的内容写到 AOF 文件开头。这样做的好处是可以结合 RDB 和 AOF 的优点, 快速加载同时避免丢失过多的数据。当然缺点也是有的, AOF 里面的 RDB 部分就是压缩格式不再是 AOF 格式,可读性较差。
如何选择合适的持久化方式
- 一般来说, 如果想达到足以媲美PostgreSQL的数据安全性,你应该同时使用两种持久化功能。在这种情况下,当 Redis 重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
- 如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失,那么你可以只使用RDB持久化。
- 有很多用户都只使用AOF持久化,但并不推荐这种方式,因为定时生成RDB快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比AOF恢复的速度要快,除此之外,使用RDB还可以避免AOF程序的bug。
- 如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式。