redis支持两种方式的持久化,一种是快照方式(snapshotting),也称RDB方式;两一种是追加文件方式(append-only file),也称AOF方式。RDB方式是redis默认的持久化方式。
Redis提供了两种持久化的方式:
- RDB(Redis DataBase)模式,就是在不同的时间点,将Redis存储的数据生成快照并存储到磁盘等介质上;
- AOF(Append Only File)模式,则换了一个角度来实现持久化,那就是将Redis执行过的所有写指令记录下来,在下次Redis重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了。
RDB和AOF两种方式可以同时使用,在这种情况下如果Redis重启,则会优先采用AOF方式来进行数据恢复,这是因为AOF方式的数据恢复完整度更高。
没有数据持久化的需求,也完全可以关闭RDB和AOF方式,这样的话,Redis将变成一个纯内存数据库,就像memcache一样。
RDB模式
Redis在进行数据持久化的过程中,会先将数据写入到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持久化好的文件。正是这种特性,让我们可以随时来进行备份,因为快照文件总是完整可用的。
对于RDB方式,Redis会单独创建(fork)一个子进程来进行持久化,而主进程是不会进行任何IO操作的,这样就确保了Redis极高的性能。
如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。
虽然RDB有不少优点,但它的缺点也是不容忽视的。如果对数据的完整性非常敏感,那么RDB方式就不太适合,因为即使每5分钟都持久化一次,当Redis故障时,仍然会有近5分钟的数据丢失。所以,Redis还提供了另一种持久化方式,那就是AOF。
使用
1:关闭rdb配置。关闭RDB只需要将所有的save保存策略注释掉即可
1 | 注释以下命令 |
2: 可以手动执行命令生成RDB快照,进入redis客户端执行命令save或bgsave可以生成dump.rdb文件,每次命令执行都会将所有redis内存快照到一个新的rdb文件里,并覆盖原有rdb快照文件。
AOF模式
通过配置Redis.conf中的“appendonly yes”就可以打开AOF功能。如果有写操作(如SET等),Redis就会被追加到AOF文件的末尾。
默认的AOF持久化策略是每秒钟fsync一次(fsync是指把缓存中的写指令记录到磁盘中),因为在这种情况下,Redis仍然可以保持很好的处理性能,即使Redis故障,也只会丢失最近1秒钟的数据。
如果在追加日志时,恰好遇到磁盘空间满、inode满或断电等情况导致日志写入不完整,也没有关系,Redis提供了Redis-check-aof工具,可以用来进行日志修复。
AOF 后台执行的方式和 RDB 有类似的地方,fork 一个子进程,主进程仍进行服务,子进程执行 AOF 持久化,数据被 dump 到磁盘上。与 RDB 不同的是,后台子进程持久化过程中,主进程会记录期间的所有数据变更(主进程还在服务),并存储在 server.aof_rewrite_buf_blocks 中;后台子进程结束后,Redis更新缓存追加到 AOF 文件中,是 RDB 持久化所不具备的。
因为采用了追加方式,如果不做任何处理的话,AOF文件会变得越来越大,为此,Redis提供了AOF文件重写(rewrite)机制,即当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。举个例子或许更形象,假如我们调用了100次INCR指令,在AOF文件中就要存储100条指令,但这明显是很低效的,完全可以把这100条指令合并成一条SET指令,这就是重写机制的原理。在进行AOF重写时,仍然是采用先写临时文件,全部完成后再替换的流程,所以断电、磁盘满等问题都不会影响AOF文件的可用性。
AOF重写的内部运行原理,有必要了解一下。
在重写即将开始之际,Redis会创建(fork)一个“重写子进程”,这个子进程会首先读取现有的AOF文件,并将其包含的指令进行分析压缩并写入到一个临时文件中。
与此同时,主工作进程会将新接收到的写指令一边累积到内存缓冲区中,一边继续写入到原有的AOF文件中,这样做是保证原有的AOF文件的可用性,避免在重写过程中出现意外。
当“重写子进程”完成重写工作后,它会给父进程发一个信号,父进程收到信号后就会将内存中缓存的写指令追加到新AOF文件中。
当追加结束后,Redis就会用新AOF文件来代替旧AOF文件,之后再有新的写指令,就都会追加到新的AOF文件中了。
虽然优点多多,但AOF方式也同样存在缺陷,比如在同样数据规模的情况下,AOF文件要比RDB文件的体积大。而且,AOF方式的恢复速度也要慢于RDB方式。
如果运气比较差,AOF文件出现了被写坏的情况,也不必过分担忧,Redis并不会贸然加载这个有问题的AOF文件,而是报错退出。这时可以通过Redis-check-aof工具来修复文件,确认问题点后再重启Redis。
使用
1: 开启
1 | appendonly yes |
2: 设置多久将数据fsync到磁盘一次
1 | 1 appendfsync always:每次有新命令追加到AOF文件时就执行一次 fsync ,非常慢也非常安全。 |
推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性
3:配置aof自动重写频率
1 | 1# auto‐aof‐rewrite‐min‐size 64mb //aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就很快,重写的意义不大 |
当然AOF还可以手动重写,进入redis客户端执行命令bgrewriteaof重写AOF
redis4.0 混合持久化
重启 Redis 时,我们很少使用 RDB来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 RDB来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。 Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。通过如下配置可以开启混合持久化(必须先开启aof):
1 | aof‐use‐rdb‐preamble yes |
如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。于是在 Redis 重启的时候,可以先加载 RDB 的内容,然后再重放增量 AOF 日志就可以完全替代之前的AOF 全量文件重放,因此重启效率大幅得到提升。