Redis 持久化、写时复制技术

Redis持久化

持久化是指将 Redis 内存中的数据保存到磁盘上,以便在系统故障或者重启之后,可以重新载入数据。Redis 支持两种持久化方式:RDB 持久化和 AOF 持久化。

两种持久化方式:RDB和AOF。

RDB 持久化

通过将内存中的数据周期性地快照到磁盘上,以便在系统故障或重启时恢复数据。RDB文件是一个二进制文件,包含了当前Redis数据库状态的所有数据。

RDB持久化的实现过程如下:

  1. Redis会fork出一个子进程,负责将Redis当前内存中的数据写入RDB文件中。
  2. 子进程首先将所有键值对写入临时文件中。
  3. 当所有键值对都写入完毕后,子进程用新的RDB文件替换旧的RDB文件。
  4. 在此期间,Redis主进程仍然可以处理客户端请求,并向子进程发送新的写命令以更新临时文件。
  5. 与此同时,Redis还会记录RDB文件生成的时间戳,以及最后一次成功执行BGSAVE命令的时间戳。

在使用RDB持久化时,需要注意以下几点:

  1. RDB持久化是异步操作,可以配置保存数据的时间间隔。如果时间间隔太短,可能会影响Redis的性能;如果时间间隔太长,可能会导致数据丢失。
  2. 在大型数据集的情况下,RDB持久化可能会占用大量CPU和内存资源,因此应该在闲时进行。
  3. RDB文件通常是压缩的,如果需要查看或修改RDB文件,需要使用特定的工具。

在Redis.conf配置文件中,有两个参数用来控制持久化方式:save和appendonly。其中,save参数表示进行RDB持久化的时间界限,默认值是save 900 1,表示在900秒内,如果至少有1个key发生了变化,就进行一次持久化操作。appendonly参数用来开启AOF持久化模式,值为yes表示开启,no表示关闭。

RDB的触发机制:Redis支持自动触发和手动触发两种方式进行RDB持久化。自动触发可以通过配置save参数来设置触发条件,手动触发可以通过Redis命令BGSAVE和SAVE来触发。

RDB文件格式:RDB文件是一个二进制文件,由多个键值对组成。每个键值对根据数据类型采用不同的存储方式,其中字符串类型的键值对长度最为简单明了。

RDB文件的恢复:RDB文件可以通过Redis的LOAD命令进行加载,成功加载后,Redis会将数据载入内存中。在Redis启动时,如果发现有RDB文件存在,则会自动进行载入,从而保证数据不会丢失。

为了避免在进行RDB备份时影响Redis的性能,可以通过调整Redis的进程优先级、增大操作系统的内核缓冲区等方式来优化RDB持久化。

RDB持久化相关命令

  • SAVE:同步执行一个快照保存操作,即将当前内存中的数据以快照形式保存到磁盘上,期间不能进行任何其他操作。
  • BGSAVE:异步执行一个快照保存操作,即将当前内存中的数据以快照形式保存到磁盘上,不会阻塞其他命令。
  • LASTSAVE:返回最后一次成功执行 SAVE 命令的时间戳。
  • SHUTDOWN:关闭 Redis 服务器,先执行 BGSAVE 命令保存数据到磁盘上,然后再关闭。
  • CONFIG SET save seconds changes:设置 RDB 持久化规则,seconds 表示在多长时间内如果发生了指定数量的修改就自动执行 BGSAVE 命令,changes 表示在多少次修改之后自动执行 BGSAVE 命令。
  • FLUSHALL:清空当前 Redis 实例中所有的数据。
  • FLUSHDB:只清空当前数据库中的数据,不影响其他数据库。
  • BGREWRITEAOF:异步执行 AOF 重写操作,与 BGSAVE 类似,不会阻塞其他命令。

AOF持久化

它记录所有写操作命令,并将其追加到一个文件中。当Redis重启时,利用这个文件可以恢复数据库的状态。

具体实现过程如下:

  1. Redis在处理每个写操作命令时,将该命令追加到AOF文件的末尾。
  2. AOF文件通常以文本格式保存,方便查看和修改。
  3. 为了防止AOF文件过大,占用过多磁盘空间,Redis提供了多种AOF重写机制,例如定期或按照规定条件进行重写。AOF重写可以生成新的AOF文件,包含了当前Redis数据库状态的所有数据。
  4. 通过AOF文件恢复数据时,Redis会顺序读取AOF文件中的命令并执行,以还原数据库的状态。

AOF持久化相比于RDB持久化,有以下几个优势:

  1. AOF持久化记录了所有写入操作,因此更可靠。
  2. AOF文件通常比RDB文件更小。
  3. 在某些场景下,AOF恢复速度可能比RDB持久化更快。

但AOF持久化也有缺点:

  1. AOF文件通常是文本格式,对性能有一定影响。
  2. 如果不及时进行AOF重写,AOF文件大小可能会变得非常大,对磁盘和I/O性能造成影响。
  3. 当使用AOF持久化时,Redis会频繁地进行写入操作,可能会降低性能。

AOF的写入模式:AOF支持两种写入模式,即always和everysec。always模式表示每个Redis命令都会被立即写入到AOF文件中,而everysec模式则表示AOF缓冲区中的命令会以1秒的频率写入AOF文件中。

AOF重写:为了避免AOF文件过大导致IO性能下降,Redis提供了AOF重写机制。通过AOF重写,Redis会遍历内存中的数据,并生成一份新的AOF文件来替换原来的AOF文件,从而达到缩减文件大小的效果。

AOF文件重播:在Redis重启时,如果存在AOF文件,则Redis会通过重播AOF文件中的命令来恢复数据。在进行重播时,Redis会对每条命令进行解析,并执行对应的操作,从而还原出内存中的数据。

AOF持久化相关命令:

  • BGSAVE:异步执行一个快照保存操作,即将当前内存中的数据以快照形式保存到磁盘上,不会阻塞其他命令。
  • SAVE:同步执行一个快照保存操作,即将当前内存中的数据以快照形式保存到磁盘上,期间不能进行任何其他操作。
  • LASTSAVE:返回最后一次成功执行 SAVE 命令的时间戳。
  • SHUTDOWN:关闭 Redis 服务器,先执行 BGSAVE 命令保存数据到磁盘上,然后再关闭。
  • AOF REWRITE:重写 AOF 文件,即将 AOF 文件中的数据转换成一系列命令来重新构建数据库。该命令可以减小 AOF 文件的大小,同时也可以清除 AOF 文件中的错误命令。
  • BGREWRITEAOF:异步执行 AOF 重写操作,与 BGSAVE 类似,不会阻塞其他命令。
  • CONFIG SET appendonly yes/no:开启或关闭 AOF 持久化功能。
  • CONFIG SET appendfsync always/everysec/no:设置 AOF 写入策略,always 表示每个 Redis 命令都要立即写入 AOF 文件,everysec 表示每秒钟将写入 AOF 文件的命令写入磁盘缓存区,no 表示不写入 AOF 文件。

异步持久化

异步持久化是指在执行持久化操作时,不会阻塞 Redis 服务器处理其他请求。Redis 支持异步持久化的方式来执行 BGSAVE 和 BGREWRITEAOF 命令。这两个命令都会在后台执行快照保存操作,所以不会阻塞其他客户端的请求。

Redis 支持两种异步持久化方式:

BGSAVE:

将内存中的数据以快照的形式保存到磁盘上,该命令会在后台新开一个进程进行执行。BGSAVE 命令会先将内存中的数据写入到一个临时文件中,然后再将该文件重命名为最终的 RDB 文件,这样可以避免在执行过程中产生错误导致原始的 RDB 文件被覆盖。BGSAVE 命令期间不会阻塞客户端的请求,但是它可能会占用大量的 CPU 和内存资源,可能会影响 Redis 的性能。

BGSAVE的过程如下:

  1. Redis主进程调用fork()函数创建子进程;
  2. 子进程将数据写入临时文件中;
  3. 写入完成后,子进程会将临时文件重命名为持久化文件;
  4. 清理旧的持久化文件;
  5. 主进程继续接收客户端请求,子进程则负责保存数据。

在这个过程中,主进程和子进程之间是通过IPC(进程间通信)机制进行交互的。主进程不断地将最新的数据写入到内存中,子进程则不断地将内存中的数据写入到临时文件中,并在写入完成后通知主进程进行下一轮写入。

由于BGSAVE是在子进程中完成的,因此它不会阻塞主进程的运行

BGREWRITEAOF:

将 AOF 文件中的数据以命令的形式重新执行一遍,从而减小 AOF 文件的大小,该命令也会在后台新开一个进程进行执行。与 BGSAVE 命令类似,BGREWRITEAOF 命令也会先将重写后的 AOF 文件写入到一个临时文件中,然后再将该文件重命名为最终的 AOF 文件。BGREWRITEAOF 命令也不会阻塞客户端的请求,但是它可能会占用大量的 CPU 和内存资源,可能会影响 Redis 的性能。 执行BGREWRITEAOF命令:执行BGREWRITEAOF命令后,Redis会fork一个子进程进行AOF重写操作。

BGREWRITEAOF的过程如下

  1. 子进程创建AOF文件:子进程会创建一个新的AOF文件,并将内存中的数据写入到该文件中。
  2. 主进程继续接收请求:在子进程进行AOF重写操作的同时,主进程将继续接收客户端请求并处理。
  3. 子进程完成AOF重写:当子进程完成AOF重写后,会向主进程发送一个信号。
  4. 主进程加载新的AOF文件:主进程收到子进程发送的信号后,会关闭原来的AOF文件并加载新的AOF文件。

写时复制技术

当一个Redis实例需要进行复制时,它会启动一个新的进程作为从节点,并将主节点的数据复制到从节点中。

在写入操作时,Redis使用写时复制技术来避免对主节点上的数据进行修改。具体来说,当某个键值对需要被修改时,Redis首先会将该键值对复制到一个新的地址中,然后将修改操作应用于新地址上的值。这样就避免了对主节点上的数据进行修改,从而保证了主节点数据的完整性。

写时复制技术只适用于对键值对进行修改的场景。如果对hash、list、set等复杂数据类型进行修改,则需要对整个数据结构进行复制。这会带来额外的开销和内存消耗。

在 Redis 的复制拓扑结构中,有以下几个关键角色:

  1. 主节点(Master):负责接收来自客户端的写入请求,并将数据复制到从节点。
  2. 从节点(Slave):复制主节点的数据,并响应读请求,可以提升为主节点。
  3. Sentinel:用于监控 Redis 实例的运行状况,并进行故障转移。

Redis 的复制拓扑结构通常是一个主节点对多个从节点的结构。当主节点接收到写入请求时,它会先更新自己的数据,并将更新操作发送给所有的从节点。每个从节点在收到更新操作后会执行相同的操作,从而保证所有节点的数据一致性。

在 Redis 中,从节点可以再次成为主节点。这个过程叫做故障转移(failover),当一个主节点失效时,Sentinel 会检测到主节点的失效并选择其中一个从节点作为新的主节点,从而保证系统的可用性。

数据同步机制

当 Redis 主节点接收到写操作时,它会将这些操作记录在内存中,并发送给所有从节点。从节点接收到这些操作后,会通过一个缓冲区将这些操作记录下来,然后再根据一定的策略将这些操作应用到自己的数据集中。

写时复制的过程中,Redis 主节点和从节点之间采用异步复制的方式进行同步。主节点将写操作记录到内存中,并立即返回给客户端;而从节点则通过一个专门的后台线程从主节点上获取并处理这些写操作。不同的节点之间可能存在较小的延迟,在同步期间从节点可能无法及时获取到最新的写操作,因此从节点的数据可能会出现一定程度的滞后。

为了解决这个问题,Redis 采用了心跳机制和复制偏移量(replication offset)来保证数据的一致性。从节点会发送心跳消息给主节点,以检查自己是否与主节点保持连接。同时,主节点会在每次写操作后将当前的复制偏移量记录下来,并将其发送给从节点。从节点可以通过比较自己的复制偏移量和主节点的复制偏移量来确定自己的数据是否已经与主节点保持一致。如果发现数据不一致,从节点会向主节点请求重新同步数据。

主节点切换机制

主节点切换机制是通过引入新的节点来实现的,叫做“从节点晋升为主节点”。

当 Redis 的主节点发生故障时,需要采取相应的措施来保证系统的可用性。这时,Redis 会自动将某个从节点晋升为主节点,作为新的主节点运行。

具体步骤如下:

  1. Redis 会检测主节点是否正常工作,如果发现主节点无法正常工作,则开始进行主节点切换。
  2. Redis 会选择一个可靠的从节点作为新的主节点,并将其升级为主节点。
  3. 新的主节点会向其他从节点发送同步数据的请求,并等待响应。
  4. 一旦所有从节点完成数据同步,新的主节点就开始接受客户端请求,并对外提供服务。

猜你喜欢

转载自blog.csdn.net/weixin_52622200/article/details/130307887