redis支持两种方式的持久化,一种是RDB方式,一种是AOF方式。
RDB方式会根据指定的规则“定时”将内存中的数据存储到硬盘上,AOF方式会在每次执行命令后将命令本身记录下来。
两种持久化方式可以单独使用其中一种,但是更多情况下是将二者结合使用。
RDB方式:
RDB方式的持久化是通过快照完成的,当符合一定条件时redis会自动将内存中的所有数据生成一份副本并存储在硬盘上,这个过程即为“快照”。
redis会在以下几种情况下对数据进行快照:
- 根据配置规则进行自动快照
- 用户执行save或bgsave命令
- 执行flushall命令
- 执行复制时
1)根据配置进行自动快照:/usr/local/etc/redis.conf配置文件中:
save 900 1
save 300 10
save 60 10000
2)用户执行save或bgsave命令:
除了让redis自动进行快照外,当进行服务重启、手动迁移以及备份时我们也会需要手动执行快照操作。redis提供了save和bgsave来完成这一任务。
save:Synchronously save the dataset to disk。当执行save时,redis同步地进行快照操作,在快照执行的过程中会阻塞所有来自客户端的请求。当数据库中的数据比较多时,这一过程会导致redis较长时间不响应,所以要尽量避免在生产环境中使用这一命令。
bgsave:Asynchronously save the dataset to disk。需要手动执行快照时推荐使用bgsave命令。bgsave可以在后台异步地进行操作,快照的同时服务器还可以继续响应来自客户端的请求。执行bgsave后redis会立即返回ok表示开始执行快照操作,如果想知道快照是否完成,可以通过lastsave命令获取最近一次成功执行快照的时间,返回结果是一个Unix时间戳。
3)执行flushall命令:
当执行flushall时,不论清空数据库的过程是否触发了自动快照条件,只要自动快照条件不为空,redis就会执行一次快照操作。当没有定义自动快照条件时,执行flushall则不会进行快照。
4)执行复制时:
当设置了主从模式时,redis会在复制初始化时进行自动快照。当使用复制操作时,即使没有定义自动快照条件,并且没有手动执行过快照操作,也会生成rdb快照文件。
快照的原理:
可以通过配置dir和dbfilename两个参数分别指定快照文件的存储路径和文件名。快照的过程:
1) redis使用fork函数复制一份当前进程(父进程)的副本(子进程)
2) 父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘的临时文件
3) 当子进程写入完所有数据后会用该临时文件替换旧的rdb文件,至此一次快照操作完成
rdb文件是经过压缩的二进制格式,所以占用的空间会小于内存中的数据大小,更加利于传输。redis启动后会读取rdb快照文件,将数据从硬盘载入到内存。
通过rdb方式实现持久化,一旦redis异常退出,就会丢失最后一次快照以后更改的所有数据。这就需要开发者根据具体的应用场合,通过组合设置自动快照条件的方式来将可能发生的数据损失控制在能够接受的范围。例如使用redis存储缓存数据时,丢失最近几秒的数据或者丢失最近更新的几十个key并不会有很大影响。如果数据相对重要,希望将损失降到最小,则可以使用aof方式进行持久化。
AOF方式:
当使用redis存储非临时数据时,一般需要打开AOF持久化来降低进程中止导致的数据丢失。AOF可以将redis执行的每一条写命令追加到硬盘文件中,这一过程显然会降低redis的性能,但是大部分情况下这个影响是可以接受的,另外使用较快的硬盘可以提高AOF的性能。
redis.conf:appendonly yes
开启AOF持久化后每执行一条会更改redis中数据的命令,redis就会将该命令写入硬盘中的AOF文件。AOF文件以纯文本的形式记录了redis执行的写命令。随着执行的命令越来越多,AOF文件的大小也会越来越大,即使内存中的实际数据可能并没有多少。因此我们希望redis可以自动优化AOF文件,redis也是这样做的,每当达到一定条件时redis就会自动重写AOF文件:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
除了让redis自动执行重写外,我们还可以使用bgrewriteaof命令手动执行aof重写。在启动时redis会逐个执行aof文件中的命令来将硬盘中的数据载入到内存中,载入的速度相较rdb会慢一些。
虽然每次执行更改数据库内容的操作时,aof都会将命令记录在aof文件中,但是事实上,由于操作系统的缓存机制,数据并没有真正地写入硬盘,而是进入了系统的硬盘缓存。在默认情况下系统每30秒会执行一次同步操作,以便将硬盘缓存中的内容真正地写入硬盘,在这30秒的过程中如果系统异常退出会导致硬盘缓存中的数据丢失。一般来说启用aof持久化的应用都无法容忍这样的损失,这就需要redis在写入aof文件后主动要求将缓存内容同步到硬盘中:
appendfsync always/everysec/no
默认情况下redis采用everysec规则,即每秒执行一次同步操作。
always:每次执行写入都会执行同步,最安全也最慢
no:不主动进行同步操作,完全交给操作系统来做(每30秒一次),最快但最不安全
redis允许同时开启aof和rdb,既保证了数据安全又使得进行备份等操作十分容易。此时重新启动redis后redis会使用aof文件来恢复数据,因为aof方式的持久化可能丢失的数据更少。