redis 的数据全部在内存中,如果突然宕机,数据就会全部丢失,因此需要持久化来保证 Redis 的数据不会因为故障而丢失,redis 重启的时候可以重新加载持久化文件来恢复数据;
在配置文件中配置
###### aof ###### # redis.cnf appendonly no appendfilename "appendonly.aof" # aof策略选择: # appendfsync always appendfsync everysec # 默认情况下是这个 # appendfsync no # auto-aof-rewrite-percentage 为 0 则关闭 aof 复写 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb # yes 如果 aof 数据不完整,尽量读取最多的格式正确的数据; # no 如果 aof 数据不完整 报错,可以通过 redis-check-aof 来修复 aof 文件; aof-load-truncated yes # 开启混合持久化 aof-use-rdb-preamble yes ###### rdb ###### # 关闭rdb save "" # save 3600 1 # save 300 100 # save 60 10000
append only file
aof 日志存储的是 Redis 服务器的顺序指令序列,aof 日志只记录对内存修改的指令记录;持久化保存的是协议数据;
通过重放(replay)aof 日志中指令序列来恢复 Redis 当前实例的内存数据结构的状态
set key val # 开启 aofappendonly yes # 关闭 aof复写 auto-aof-rewrite-percentage 0 # 关闭 混合持久化 aof-use-rdb-preamble no # 关闭 rdbsave 使用aof时必须关闭rdb save "" # 设置aof文件名 appendfilename "appendonly.aof"
# 1. 每条命令刷盘 redis 事务才具备持久性 # appendfsync always # 2. 每秒刷盘 appendfsync everysec # 3. 交由系统刷盘 # appendfsync no
随着时间越长,aof 日志会越来越长,如果 redis 重启,重放整个 aof 日志会非常耗时,导致redis 长时间无法对外提供服务;
aof 持久化策略会持久化所有修改命令;里面的很多命令其实可以合并或者删除;如:
# 无意义的入队列和出队列,可以不做 lpush list a lpop list
aof rewrite 在 aof 的基础上,满足一定策略则 fork 进程,根据当前内存状态,转换成一系列的 redis 命令,序列化成一个新的 aof 日志文件中,序列化完毕后再将操作期间发生的增量 aof 日志追加到新的 aof 日志文件中国你,追加完毕后替换旧的 aof 日志文件;以此达到对 aof 日志瘦身的目的;
fork进程有两种方式,一种是命令(bgrewriteaof),一种是配置文件。
注意:aof rewrite 开启的前提是开启 aof;
命令方式:
lpush list mark lpush list king lpush list darren bgrewriteaof # 此时会将上面三个命令进行合并成为一个命令 # 合并策略:会先检测键所包含的元素数量,如果超过 64 个会使用多个命令来记录键的值; hset hash mark 10001 hset hash darren 10002 hset hash king 10003 hdel hash mark bgrewriteaof # 此时aof中不会出现mark,设置mark跟删除mark变得像从来没操作过
配置方式:
# 开启 aof appendonly yes # 开启 aof复写 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb # 关闭 混合持久化 aof-use-rdb-preamble no # 关闭 rdb save ""
# 1. redis 会记录上次aof复写时的size,如果之后累计超过了原来的size,则会发生aof复写; auto-aof-rewrite-percentage 100 # 2. 为了避免策略1中,小数据量时产生多次发生aof复写,策略2在满足策略1的前提下需要超过 64mb才会发生aof复写; auto-aof-rewrite-min-size 64mb
aof复写在 aof 基础上实现了瘦身,但是 aof 复写的数据量仍然很大;加载会非常慢
基于 aof 或 aof 复写文件大的缺点,rdb 是一种快照持久化;它通过 fork 主进程,在子进程中将内存当中的数据键值对按照存储方式持久化到 rdb 文件中;rdb 存储的是经过压缩的二进制数据;
# 关闭 aof 同时也关闭了 aof复写 appendonly no # 关闭 aof复写 auto-aof-rewrite-percentage 0 # 关闭 混合持久化 aof-use-rdb-preamble no # 开启 rdb 也就是注释 save "" # save "" # save 3600 1 # save 300 100 # save 60 10000
# redis 默认策略如下: # 注意:写了多个 save 策略,只需要满足一个则开启rdb持久化 # 3600 秒内有以1次修改 save 3600 1 # 300 秒内有100次修改 save 300 100 # 60 秒内有10000次修改 save 60 10000
若采用 rdb 持久化,一旦 redis 宕机,redis将丢失一段时间的数据;
RDB 需要经常 fork 子进程来保存数据集到硬盘上,当数据集比较大的时候,fork 的过程是非常耗时的,可能会导致 Redis 在一些毫秒级内不能响应客户端的请求。如果数据集巨大并且 CPU 性能不是很好的情况下,这种情况会持续1秒,AOF 也需要 fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度。
从上面知道,rdb 文件小且加载快但丢失多,aof 文件大且加载慢但丢失少;混合持久化是吸取rdb 和 aof 两者优点的一种持久化方案;aof 复写的时候实际持久化的内容是 rdb,等持久化后,持久化期间修改的数据以 aof 的形式附加到文件的尾部;
混合持久化实际上是在 aof rewrite 基础上进行优化;所以需要先开启 aof rewrite;
# 开启 aof appendonly yes # 开启 aof复写 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb # 开启 混合持久化 aof-use-rdb-preamble yes # 关闭 rdb save "" # save 3600 1 # save 300 100 # save 60 10000
问题:拷贝持久化文件是否安全?
是安全的,持久化 文件一旦被创建, 就不会进行任何修改。 当服务器要创建一个新的持久化文件时, 它先将文件的内容保存在一个临时文件里面, 当临时文件写入完毕时, 程序才使用rename(2) 原子地用临时文件替换原来的持久化文件
数据安全要考虑两个问题:
创建一个定期任务(cron job), 每小时将一个 RDB 文件备份到一个文件夹, 并且每天将一个RDB 文件备份到另一个文件夹。
确保快照的备份都带有相应的日期和时间信息, 每次执行定期任务脚本时, 使用 find 命令来删除过期的快照: 比如说, 你可以保留最近 48 小时内的每小时快照, 还可以保留最近一两个月的每日快照。
至少每天一次, 将 RDB 备份到你的数据中心之外, 或者至少是备份到你运行 Redis 服务器的物理机器之外