首页 > 技术文章 > Redis数据恢复和主从数据同步问题

zhaoguanglu 2021-06-25 22:41 原文

Redis持久化

Redis提供了两种持久化的选项,一种是快照文件(snapshotting,RDB),它会基于某个时间点将数据全部写入硬盘中(默认为dump.rdb)。另一种是只追加文件(append-only,AOF),它会在执行写入命令时将命令写入到硬盘中。Redis持久化数据最主要是为了数据备份,故障恢复,也有一些经过耗时较长的计算结果存在Redis中,如果这些数据存在硬盘中,即使服务器重启了之后,这些数据还是存在的,不用再去耗时计算了。这两种方式可以单独使用,也可以结合起来使用。最重要的还是要理解RDB和AOF的优劣势,结合自己的应用做一个权衡。

RDB 详解(Save、BGSave)

Redis 通过创建快照的方式,获得内存中某个时间点的数据副本。Redis重启时可以从 RDB 文件上恢复数据。我们也可以把 RDB 文件备份在别的服务器上。

根据上述的几个配置项,快照被写入 dir 目录下的 dbfilename 文件中。如果在新的快照文件创建完成之前,Redis服务器发生了宕机,那这期间的数据将丢失。

Redis中有两个命令可以创建快照文件, SAVEBGSAVE

  • *执行 SAVE 命令后,服务器将不会再相应任何命令,直到快照文件完成。*
  • *执行 BGSAVE 命令后,Redis父进程会调用 fork 来创建一个子进程,由子进程去负责快照文件的写入,父进程则继续处理客户端的命令请求。*
  1. 客户端可以直接向服务器发送 SAVE 或者 BGSAVE
  2. 如果设置了 save 配置项,达到配置项的要求时,Redis会自动执行 BGSAVE 命令。该配置项可以设置多组,如果设置了多组,只要达到其中一组的要求,就会执行BGSAVE
  3. Redis通过SHUTDOWN 指令,或者接收到标准 TERM 信号时,会执行 SAVE 命令,阻塞所有客户端,直到 SAVE 命令执行完成后,关闭服务器
  4. Redis配置了复制集之后,从服务器向主服务器发来 SYNC 命令,主服务器会执行 BGSAVE 命令,然后将快照文件发给从服务器

需要注意的是, 执行 BGSAVE 命令可能会造成服务器暂停几毫秒或者几秒,具体时长要根据数据量的大小以及服务器的配置来看。在数据量特别大,服务器内存吃紧的情况下,可能会造成长时间的停顿,甚至宕机。通常情况下, BGSAVE 是要比 SAVE 好一些,因为不会影响客户端的请求,不过在数据量巨大的情况下, BGSAVE 可能会比 SAVE 指令耗时更长。所以还是要结合具体的数据情况来选择。如果可以接受数据丢失5分钟,15分钟,1小时甚至更长时间的数据的话,甚至可以关闭自动保存,由客户端决定什么时候来执行快照副本的创建。

RDB 优点

  • 冷备份,例如:可以设置每个小时归档数据集,并备份至其他服务器,发生灾难时可以选择恢复数据集的不同副本。
  • 对 Redis 的读写影响小,最大限度的提高了性能。父进程会fork一个子进程区做数据集的归档,不会影响父进程的工作。
  • 在恢复数据集时,RDB比AOF更加高效

RDB 缺点

  • 在发生灾难的时候,RDB会比AOF丢失的数据多。可以通过设置来更改保存点,一般设置为5分钟。
  • RDB 每次在fork子线程来执行RDB快照文件时,如果数据文件特别大且CPU性能不佳,可能造成服务暂停几毫秒或者几秒。

AOF (append-only)

关于 appendfsync 的说明

选项同步频率
always每次执行写入操作都执行fsync,这将非常影响性能,严重降低Redis的吞吐
everysec每隔1s执行一次 fsync,显示的将多个写入命令同步到硬盘,性能非常好,如果丢失数据也只是丢失1s内的数据
no不执行 fsync ,交给操作系统去处理。一般Linux是每隔30s刷新一次数据到磁盘上,取决于内核的精准调整

AOF 详解

AOF机制对每条写入命令作为日志,以append-only的模式写入一个日志文件中,在redis重启的时候,可以通过回放AOF日志中的写入指令来重新构建整个数据集。 ****Redis并不会将数据直接写入硬盘中,而是会先将数据写进linux os cache,然后在通过配置的appendfsync 设置的时间来执行fsync操作,强行将数据刷入磁盘文件。 AOF是存放每条的写命令,所以会不断扩大,当大到一定程度****,AOF做rewrite操作,就会基于当时redis内存中的数据,来重新构造一个更小的AOF文件,然后将旧的文件删掉。

AOF 优点

  • AOF可以更好的保护数据不丢失,一般AOF每隔一秒,通过后台线程执行一次fsync,最多丢失1s的数据。可以通过设置改为每次写入数据时都执行fsync,不过这非常影响性能。
  • AOF日志仅仅时附加日志,如果因为某些原因导致只写入一般,也可以通过redis-check-aof 轻松修复。
  • AOF日志文件过大时,会在后台执行rewrite操作,不会影响客户端的读写
  • AOF日志文件可能性好,因为记录的时一条一条的指令。

AOF 缺点

  • AOF日志通常比RDB数据快照文件更大
  • 做数据恢复的时候可能会比RDB慢
  • 做定期的冷备没有RDB方便

Redis主从数据同步问题

Redis主从复制的核心原理:当启动一个 slave node 的时候,它会发送一个 PSYNC 命令给 master node。如果这是slave node 初次连接到 master node,那么会触发一次 full resynchronization 全量复制。此时 master 会启动一个后台线程,开始生成一份 RDB 快照文件,同时还会将从客户端 client 新收到的所有写命令缓存在内存中。RDB 文件生成完毕后, master会将这个 RDB 发送给 slave,slave 会先写入本地磁盘,然后再从本地磁盘加载到内存中,接着master会将内存中缓存的写命令发送到 slave,slave 也会同步这些数据。slave node 如果跟master node 有网络故障,断开了连接,会自动重连,连接之后 master node 仅会复制给 slave 部分缺少的数据。

*主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。*

全量同步

Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下:

  1. ​ 从服务器连接主服务器,发送SYNC命令;
  2. ​ 主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
  3. ​ 主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
  4. ​ 从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
  5. ​ 主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
  6. ​ 从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;

在这里插入图片描述

增量同步

Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。

推荐阅读