Redis知识总结-持久化原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lin051124/article/details/89762901

Redis知识总结-持久化原理

Redis的持久化原理

持久化官方文档

持久化中文文档

Redis提供了两种持久化方式:

  • RDB(快照):在指定的时间间隔能对你的数据进行快照存储。
  • AOP(追加文件):记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据。

快照 RDB

1. 工作原理

​ 在默认情况下,Redis将数据库快照保存在dump.rdb的二进制文件中,这种持久化方式叫快照(snapshot)。

当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:

  1. Redis 调用 fork() ,同时拥有父进程和子进程。
  2. 子进程将数据集写入到一个临时 RDB 文件中。
  3. 当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。

在Redis中RDB持久化的触发分为两种:自己手动触发与Redis定时触发。

手动触发可以通过以下两个命令:

  • save:会阻塞当前Redis服务器,直到持久化完成,线上应该禁止使用。
  • bgsave:该触发方式会fork一个子进程,由子进程负责持久化过程,因此阻塞只会发生在fork子进程的时候。

自动触发主要通过以下几种情况:

  • 根据配置文件的save m n配置规则触发。
  • 从节点全量复制时,主节点发送rdb文件给从节点完成复制操作,主节点会触发 bgsave
  • 执行 debug reload 时;
  • 执行 shutdown时,如果没有开启aof,也会触发。

2. 优点

  1. RDB 是一个非常紧凑(compact)的文件,它保存了 Redis 在某个时间点上的数据集。 这种文件非常适合用于进行备份。
  2. RDB 非常适用于灾难恢复(disaster recovery):它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心。
  3. RDB的性能很好,需要进行持久化时,主进程会fork一个子进程出来,然后把持久化的工作交给子进程,自己不会有相关的I/O操作。
  4. 比起AOF,在数据量比较大的情况下,RDB的启动速度更快。

3. 缺点

  1. RDB容易造成数据的丢失。假设每5分钟保存一次快照,如果Redis因为某些原因不能正常工作,那么从上次产生快照到Redis出现问题这段时间的数据就会丢失了。
  2. 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 重写的执行步骤:

  1. Redis 执行 fork() ,现在同时拥有父进程和子进程。
  2. 子进程开始将新 AOF 文件的内容写入到临时文件。
  3. 对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾: 这样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。
  4. 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。
  5. 搞定!现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。

重写流程图

2.优点

  1. 比RDB可靠。你可以制定不同的fsync策略:不进行fsync、每秒fsync一次和每次查询进行fsync。默认是每秒fsync一次。这意味着你最多丢失一秒钟的数据。
  2. AOF日志文件是一个纯追加的文件。就算是遇到突然停电的情况,也不会出现日志的定位或者损坏问题。甚至如果因为某些原因(例如磁盘满了)命令只写了一半到日志文件里,我们也可以用redis-check-aof这个工具很简单的进行修复。
  3. 当AOF文件太大时,Redis会自动在后台进行重写。重写很安全,因为重写是在一个新的文件上进行,同时Redis会继续往旧的文件追加数据。新文件上会写入能重建当前数据集的最小操作命令的集合。当新文件重写完,Redis会把新旧文件进行切换,然后开始把数据写到新文件上。
  4. AOF把操作命令以简单易懂的格式一条接一条的保存在文件里,很容易导出来用于恢复数据。例如我们不小心用FLUSHALL命令把所有数据刷掉了,只要文件没有被重写,我们可以把服务停掉,把最后那条命令删掉,然后重启服务,这样就能把被刷掉的数据恢复回来。

3.缺点

  1. 在相同的数据集下,AOF文件的大小一般会比RDB文件大。
  2. 在某些fsync策略下,AOF的速度会比RDB慢。通常fsync设置为每秒一次就能获得比较高的性能,而在禁止fsync的情况下速度可以达到RDB的水平。
  3. 在过去曾经发现一些很罕见的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 持久化

  1. 为最新的 dump.rdb 文件创建一个备份。

  2. 将备份放到一个安全的地方。

  3. 执行以下两条命令:

    redis-cli> CONFIG SET appendonly yes
    
    redis-cli> CONFIG SET save ""
    
  4. 确保命令执行之后,数据库的键的数量没有改变。

  5. 确保写命令会被正确地追加到 AOF 文件的末尾。

备份 Redis 数据

  • 创建一个定期任务(cron job), 每小时将一个 RDB 文件备份到一个文件夹, 并且每天将一个 RDB 文件备份到另一个文件夹。
  • 确保快照的备份都带有相应的日期和时间信息, 每次执行定期任务脚本时, 使用 find 命令来删除过期的快照: 比如说, 你可以保留最近 48 小时内的每小时快照, 还可以保留最近一两个月的每日快照。
  • 至少每天一次, 将 RDB 备份到你的数据中心之外, 或者至少是备份到你运行 Redis 服务器的物理机器之外。

性能与实践

  1. 如果Redis中的数据并不是特别敏感或者可以通过其它方式重写生成数据,可以关闭持久化,如果丢失数据可以通过其它途径补回;
  2. 自己制定策略定期检查Redis的情况,然后可以手动触发备份、重写数据;
  3. 单机如果部署多个实例,要防止多个机器同时运行持久化、重写操作,防止出现内存、CPU、IO资源竞争,让持久化变为串行;
  4. 可以加入主从机器,利用一台从机器进行备份处理,其它机器正常响应客户端的命令;
  5. RDB持久化与AOF持久化可以同时存在,配合使用。

猜你喜欢

转载自blog.csdn.net/lin051124/article/details/89762901