Redis知识总结-持久化原理
Redis的持久化原理
Redis提供了两种持久化方式:
- RDB(快照):在指定的时间间隔能对你的数据进行快照存储。
- AOP(追加文件):记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据。
快照 RDB
1. 工作原理
在默认情况下,Redis将数据库快照保存在dump.rdb的二进制文件中,这种持久化方式叫快照(snapshot)。
当 Redis 需要保存 dump.rdb
文件时, 服务器执行以下操作:
- Redis 调用 fork() ,同时拥有父进程和子进程。
- 子进程将数据集写入到一个临时 RDB 文件中。
- 当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
在Redis中RDB持久化的触发分为两种:自己手动触发与Redis定时触发。
手动触发可以通过以下两个命令:
- save:会阻塞当前Redis服务器,直到持久化完成,线上应该禁止使用。
- bgsave:该触发方式会fork一个子进程,由子进程负责持久化过程,因此阻塞只会发生在fork子进程的时候。
自动触发主要通过以下几种情况:
- 根据配置文件的save m n配置规则触发。
- 从节点全量复制时,主节点发送rdb文件给从节点完成复制操作,主节点会触发
bgsave
; - 执行
debug reload
时; - 执行
shutdown
时,如果没有开启aof,也会触发。
2. 优点
- RDB 是一个非常紧凑(compact)的文件,它保存了 Redis 在某个时间点上的数据集。 这种文件非常适合用于进行备份。
- RDB 非常适用于灾难恢复(disaster recovery):它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心。
- RDB的性能很好,需要进行持久化时,主进程会fork一个子进程出来,然后把持久化的工作交给子进程,自己不会有相关的I/O操作。
- 比起AOF,在数据量比较大的情况下,RDB的启动速度更快。
3. 缺点
- RDB容易造成数据的丢失。假设每5分钟保存一次快照,如果Redis因为某些原因不能正常工作,那么从上次产生快照到Redis出现问题这段时间的数据就会丢失了。
- RDB使用
fork()
产生子进程进行数据的持久化,如果数据比较大的话可能就会花费点时间,造成Redis停止服务几毫秒。如果数据量很大且CPU性能不是很好的时候,停止服务的时间甚至会到1秒。
4. 参数配置
# RDB文件名,默认为dump.rdb。
dbfilename dump.rdb
# 文件存放的目录,AOF文件同样存放在此目录下。默认为当前工作目录。
dir ./
# RDB定时触发规则配置,可配置多个
save 900 1 #900秒后至少1个key有变动
save 300 10 #300秒后至少10个key有变动
save 60 10000 #60秒后至少10000个key有变动
# 禁用快照保存的功能
save ""
# 如果持久化出错,主进程是否停止写入,建议开启保护持久化的数据一致性问题
stop-writes-on-bgsave-error yes
# 是否压缩 建议没有必要开启
rdbcompression yes
# 导入时是否检查
rdbchecksum yes
追加式文件(AOF
文件)
1.工作原理
当Redis接受到会修改数据集的命令时,就会把命令追加到AOF文件里,当你重启Redis时,AOF里的命令会被重新执行一次,重建数据。
AOF主要分为两个步骤:一是对修改命令的实时写入,二是对AOF重写。AOF重写是为了减少aof文件的大小,可以手动或者自动触发,
手动触发: bgrewriteaof
。
自动触发: 就是根据配置规则来触发,当然自动触发的整体时间还跟Redis的定时任务频率有关系。
AOF 重写的执行步骤:
- Redis 执行
fork()
,现在同时拥有父进程和子进程。 - 子进程开始将新 AOF 文件的内容写入到临时文件。
- 对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾: 这样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。
- 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。
- 搞定!现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。
2.优点
- 比RDB可靠。你可以制定不同的fsync策略:不进行fsync、每秒fsync一次和每次查询进行fsync。默认是每秒fsync一次。这意味着你最多丢失一秒钟的数据。
- AOF日志文件是一个纯追加的文件。就算是遇到突然停电的情况,也不会出现日志的定位或者损坏问题。甚至如果因为某些原因(例如磁盘满了)命令只写了一半到日志文件里,我们也可以用
redis-check-aof
这个工具很简单的进行修复。 - 当AOF文件太大时,Redis会自动在后台进行重写。重写很安全,因为重写是在一个新的文件上进行,同时Redis会继续往旧的文件追加数据。新文件上会写入能重建当前数据集的最小操作命令的集合。当新文件重写完,Redis会把新旧文件进行切换,然后开始把数据写到新文件上。
- AOF把操作命令以简单易懂的格式一条接一条的保存在文件里,很容易导出来用于恢复数据。例如我们不小心用
FLUSHALL
命令把所有数据刷掉了,只要文件没有被重写,我们可以把服务停掉,把最后那条命令删掉,然后重启服务,这样就能把被刷掉的数据恢复回来。
3.缺点
- 在相同的数据集下,AOF文件的大小一般会比RDB文件大。
- 在某些fsync策略下,AOF的速度会比RDB慢。通常fsync设置为每秒一次就能获得比较高的性能,而在禁止fsync的情况下速度可以达到RDB的水平。
- 在过去曾经发现一些很罕见的BUG导致使用AOF重建的数据跟原数据不一致的问题。
4.参数配置
# 是否开启aof
appendonly yes
# 文件名称
appendfilename "appendonly.aof"
# 同步方式
#每秒fsync一次。速度快(2.4版本跟快照方式速度差不多),安全性不错(最多丢失1秒的数据)。
appendfsync everysec
# appendfsync always 每当有新命令追加到AOF的时候调用fsync。速度最慢,但是最安全。
# appendfysnc no 从不fsync,交由系统去处理。这个方式速度最快,但是安全性一般。
# aof重写期间是否同步
no-appendfsync-on-rewrite no
# 重写触发配置
auto-aof-rewrite-min-size 64MB
auto-aof-rewrite-percentage 100
# 加载aof时如果有错如何处理,如果该配置启用,在加载时发现aof尾部不正确##是,会向客户端写入一个log,但是会继续执行,如果设置为 no ,发现错误就会停止,必须修复后才能重新加载
aof-load-truncated yes
#文件重写策略
aof-rewrite-incremental-fsync yes
恢复数据
从上面我们知道Redis有两种持久化方式,那么持久化完以后,如何进行恢复数据呢?假如同时开始两种持久化方式,那么Redis是如何进行加载AOF文件、RDB文件的? Redis会OF文件是否存在,如果不存在就尝试加载RDB。那么为什么会优先加载AOF呢?因为AOF保存的数据更完整,通过上面的分析我们知道AOF基本上最多损失1s的数据。
从 RDB 持久化切换到 AOF 持久化
- 为最新的
dump.rdb
文件创建一个备份。 - 将备份放到一个安全的地方。
- 执行以下两条命令:
redis-cli> CONFIG SET appendonly yes
redis-cli> CONFIG SET save ""
- 确保命令执行之后,数据库的键的数量没有改变。
- 确保写命令会被正确地追加到 AOF 文件的末尾。
备份 Redis 数据
- 创建一个定期任务(cron job), 每小时将一个 RDB 文件备份到一个文件夹, 并且每天将一个 RDB 文件备份到另一个文件夹。
- 确保快照的备份都带有相应的日期和时间信息, 每次执行定期任务脚本时, 使用
find
命令来删除过期的快照: 比如说, 你可以保留最近 48 小时内的每小时快照, 还可以保留最近一两个月的每日快照。 - 至少每天一次, 将 RDB 备份到你的数据中心之外, 或者至少是备份到你运行 Redis 服务器的物理机器之外。
性能与实践
- 如果Redis中的数据并不是特别敏感或者可以通过其它方式重写生成数据,可以关闭持久化,如果丢失数据可以通过其它途径补回;
- 自己制定策略定期检查Redis的情况,然后可以手动触发备份、重写数据;
- 单机如果部署多个实例,要防止多个机器同时运行持久化、重写操作,防止出现内存、CPU、IO资源竞争,让持久化变为串行;
- 可以加入主从机器,利用一台从机器进行备份处理,其它机器正常响应客户端的命令;
- RDB持久化与AOF持久化可以同时存在,配合使用。