Redis复制译文

原文地址:https://redis.io/topics/replication

复制

在Redis复制的基础上,使用和配置主从复制非常简单,它允许从属Redis服务器成为主服务器的精确副本。每次链路断开时,从设备都会自动重新连接到主设备,无论主设备发生什么情况,设备都会尝试将其复制一份。

该系统使用三种主要机制:

  1. 当主和从实例连接良好时,主服务器通过发送命令流来更新从服务器,以便在主数据集中发生的数据集上复制效果:客户端写入,key过期或被驱逐等等。
  2. 当主和从之间的链路断开时,对于网络问题或者由于在主或从中检测到超时,从重新连接并尝试进行部分重新同步:这意味着它将尝试仅获取部分它在断开连接时错过的命令流。
  3. 当部分重新同步不可能时,从机将要求完全重新同步。这将涉及一个更复杂的过程,在这个过程中,主机需要创建其所有数据的快照,将其发送给从机,然后在数据集更改时继续发送命令流。

Redis默认使用异步复制,这会高延迟和高性能,是绝大多数Redis用例的自然复制模式。但是,Redis从会异步确认主定期收到的数据量。

客户端可以使用WAIT命令请求某些数据的同步复制。但WAIT只能确保在其他Redis实例中具有指定数量的已确认副本:在故障转移期间出于不同原因进行故障转移时,或者根据Redis持久性的确切配置,已确认的写入仍可能会丢失。您可以查看Sentinel或Redis集群文档以获取有关高可用性和故障转移的更多信息。本文档的其余部分主要介绍Redis基本复制的基本特性。

以下是关于Redis复制的一些非常重要的事实:

  • Redis使用异步复制,异步从到主确认处理的数据量。
  • 一个主可以有多个从。
  • 从能够接受来自其他从的连接。除了将多个从连接到同一个主之外,从也可以通过级联结构连接到其他从。自从Redis 4.0以来,所有的子从服务器都将收到与主服务器完全相同的复制流。
  • 在主端,Redis复制是非阻塞的。这意味着当一个或多个从执行初始同步或部分重新同步时,主机将继续处理查询。
  • 从侧的复制也基本上不阻塞。当从服务器正在执行初始同步时,假设您在redis.conf中配置了Redis来执行初始同步,它可以使用旧版本的数据集处理查询。否则,您可以配置Redis从服务器在复制流关闭时向客户端返回错误。但是,在初始同步之后,必须删除旧数据集,并且必须加载新数据集。在这个简短的窗口中,从将阻止传入的连接(对于非常大的数据集,这可能需要很长的时间)。自Redis 4.0以来,可以配置Redis在不同的线程中删除旧数据集,但加载新的初始数据集仍将在主线程中发生并阻色从。
  • 复制既可用于可伸缩性,也可用于只读查询的多个从(例如,可将低速O(N)操作卸载到从),或者仅用于数据安全。
  • 可以使用复制来避免让主服务器将完整数据集写入磁盘的成本:一种典型的技术包括配置主服务器redis.conf以避免永久保存到磁盘,然后连接配置为间断性保存的从服务器或启用AOF。但是,必须谨慎处理此设置,因为重新启动的主设备将从空数据集开始:如果从设备尝试与其同步,则从设备也将被清空。

主持续关闭时复制的安全性

在使用Redis复制的设置中,强烈建议在主服务器和从服务器中启用持久性。如果这种情况不可行,例如由于磁盘速度非常慢引起的延迟问题,应配置实例以避免重新引导后的自动重新启动。
为了更好地理解持续关闭配置为自动重启的主设备危险的原因,请检查以下故障模式,其中数据是从主设备及其所有从设备擦除的:

  1. 我们有一个设置,节点A充当主节点,持久性关闭,节点B和C从节点A复制。
  2. 节点A崩溃,但它有一些自动重启系统,重启该进程。但是,由于关闭了持久性,节点将以空数据集重新启动。
  3. 节点B和C将从节点A复制,节点A是空的,所以它们将有效地销毁它们的数据副本。

当Redis Sentinel用于高可用性时,关闭主服务器上的持久性以及进程的自动重启也是非常危险的。例如,主设备可以足够快地重新启动,以便Sentinel不会检测到故障,以便发生上述故障模式。

数据安全很重要,复制与配置为无持久性的主一起使用时,应禁用实例的自动重启。

Redis复制如何工作

每个Redis master都有一个复制ID:它是一个大的伪随机字符串,用于标记数据集的给定故事。每个主节点还会获得一个偏移量,该值会因为复制流的每个字节而递增,它被生产发送到从节点,以便使用修改数据集的新变化更新从节点的状态。即使没有从实际连接,复制偏移量也会增加,因此基本上每一对给定的:

Replication ID, offset

都用于标识主数据集的确切版本。

当从连接到主时,它们使用PSYNC命令为了发送它们旧的主复制ID和目前处理的偏移量。这样主可以发送所需的增量部分。但是,如果主缓冲区中没有足够的积压,或者从服务器引用了未知的历史(复制标识),则会发生完全重新同步:在这种情况下,从服务器将获得数据集的完整副本,从头开始。

这是完全同步如何工作更详细的信息:

主设备启动后台保存过程以生成RDB文件。同时它开始缓冲从客户端收到的所有新写入命令。当后台保存完成后,主服务器将数据库文件传输到从服务器,从服务器将其保存在磁盘上,然后将其加载到内存中。主机会将所有缓冲的命令发送给从机。这是作为命令流完成的,并且与Redis协议本身的格式相同。

你可以通过telnet自己尝试。在服务器执行某些工作时连接到Redis端口并发出SYNC命令。您将看到批量传输,然后主设备收到的每个命令都将在远程登录会话中重新发布。实际上,SYNC是旧协议,不再由较新的Redis实例使用,但仍然存在以实现向后兼容性:它不允许部分重新同步,因此现在使用PSYNC。

如前所述,当主从链路出于某种原因关闭时,从能够自动重新连接。如果主收到多个并发的从同步请求,它将执行一次后台保存以便为它们全部提供服务。

无盘复制

通常情况下,完全重新同步需要在磁盘上创建一个RDB文件,然后从磁盘重新加载相同的RDB,以便为从属设备提供数据。

对于慢速磁盘,这对于主设备来说可能是一个非常紧张的操作。Redis 2.8.18版是第一个支持无盘复制的版本。在此设置中,子进程直接通过网络将RDB发送给从服务器,而不使用磁盘作为中间存储。

配置

配置基本的Redis复制非常简单:只需将以下行添加到从属配置文件:

slaveof 192.168.1.1 6379

当然,你需要用主IP地址(或主机名)和端口替换192.168.1.1 6379。或者,您可以调用SLAVEOF命令,主服务器主机将启动与从服务器主机的同步。

还有一些参数用于调整主服务器在内存中执行部分重新同步的复制积压。有关更多信息,请参阅Redis发行版附带的示例redis.conf。

可以使用repl-diskless-sync配置参数启用无盘复制。为了等待更多的从设备在第一个设备之后到达,启动传输的延迟由repl-diskless-sync-delay参数控制。有关更多详细信息,请参阅Redis发行版中的示例redis.conf文件。

只读从

自Redis 2.6以来,从属设备支持默认启用的只读模式。此行为由redis.conf文件中的slave-read-only选项控制,并可使用CONFIG SET在运行时启用和禁用。

只读从将拒绝所有写入命令,因此由于错误而无法写入从是不可能的。 这并不意味着该功能旨在将一个从属实例暴露给互联网,或者更一般地说是将一个从属实例暴露给不可信客户端存在的网络,因为像DEBUG或CONFIG这样的管理命令仍然处于启用状态。但是,通过使用rename-command指令禁用redis.conf中的命令,可以提高只读实例的安全性。

您可能想知道为什么可以还原只读设置,并且可以通过写入操作来设置从属实例。如果从设备和主设备重新同步或者从设备重新启动,那么这些写入操作将被丢弃,但是将短暂数据存储在可写入从设备中有一些合理用例。

例如,计算缓慢的Set或Sorted Set操作并将它们存储到本地key中是多次观察到的使用可写入Slave的用例。

但请注意,版本4.0之前的可写入从无法使用可过期的key过期功能。这意味着如果您使用EXPIRE或其他命令为某个key设置了最大TTL值,该key将会泄漏,并且您在使用读取命令访问该key时可能会看不到它,您将在key数中看到它,仍然会使用内存。所以通常混合可写入的从属设备(以前的版本4.0)和带有TTL的key将会产生问题。

Redis 4.0 RC3及更高版本彻底解决了这个问题,现在可写入的从节点能够像主节点一样使用TTL驱逐key,但DB编号大于63(但默认情况下,Redis实例只有16个数据库)的key除外。

另请注意,由于Redis 4.0从写入仅为本地,并且不会传播到附加到该实例的子从服务器上。相反,子从服务器将始终接收与由顶级主服务器发送到中间从服务器的副本相同的复制流。因此,例如在以下设置中:

A —> B —> C

即使B是可写的,C也不会看到B写入,并且将具有与主实例A相同的数据集。

设置从属服务器以向主服务器进行身份验证

如果您的主设备通过requirepass提供密码,则在所有同步操作中配置从设备使用该密码并不重要。

要在正在运行的实例上执行此操作,请使用redis-cli并输入:

config set masterauth <password>

要永久设置它,请将其添加到您的配置文件中:

masterauth <password>

只允许写入N个附加副本

从Redis 2.8开始,只有当至少有N个从服务器连接到主服务器时,才有可能配置Redis主服务器接受写查询。

但是,由于Redis使用异步复制,因此无法确保从服务器实际接收到给定写入,因此总会有一个数据丢失窗口。

这是该功能的工作原理:

  • Redis从服务器每秒都会ping主服务器,确认处理的复制流数量。
  • Redis主将会记得它最后一次收到来自每个从的ping。
  • 用户可以配置滞后不大于最大秒数的最小数量的从站。

如果至少有N个从站,并且滞后少于M秒,则写入将被接受。

您可能认为它是一种尽力而为的数据安全机制,对于给定的写入,不能保证一致性,但至少数据丢失的时间窗限制在给定的秒数内。一般来说,绑定数据丢失优于未绑定数据。

如果条件不满足,主将会回复一个错误,写入将不被接受。

该功能有两个配置参数:

  • min-slaves-to-write <从数量>
  • min-slaves-max-lag <秒数>

有关更多信息,请查看随Redis源代码发行版一起提供的示例redis.conf文件。

Redis复制如何处理key到期

Redis过期允许key有一个有限的生存时间。这样的功能取决于实例计算时间的能力,但是,即使使用Lua脚本更改了这些key,Redis也能够正确地复制具有过期的key。

为了实现这样的功能,Redis不能依赖主从同步时钟的能力,因为这是一个无法解决的问题,并且会导致竞争条件和不同的数据集,因此Redis使用三种主要技术使过期的key的复制能够工作:

  1. 从不会过期的key,而是等待主过期的key。当一个主过期key(或由于LRU而将其驱逐)时,它会合成一个DEL命令,并将其传输到所有从。
  2. 但是,由于主驱动过期,因为主控制器无法及时提供DEL命令,所以有时从属设备中可能仍有已经逻辑超时的内存key。为了处理从使用其逻辑时钟,以报告仅用于不违反数据集一致性的读取操作(因为来自主机的新命令将到达)的key不存在。通过这种方式,从避免报告逻辑过期的key仍然存在。实际上,使用从属程序进行扩展的HTML片段缓存将避免返回已经比期望的时间更早的条目。
  3. 在执行Lua脚本期间,不会执行任何key过期。当Lua脚本运行时,从概念上讲,主服务器中的时间是冻结的,这样一个给定的密钥就可以存在或不存在。 这可以防止密钥在脚本中间过期,并且需要将相同的脚本以确保在数据集中具有相同效果的方式发送到从站。

一旦从被提升主,它就会开始独立的过期key,并且不需要任何旧的主服务器的帮助。

在Docker和NAT中配置复制

当使用Docker或其他类型的使用端口转发或网络地址转换的容器时,Redis复制需要特别小心,尤其是在使用Redis Sentinel或其他系统主INFO或ROLE命令的输出被扫描以发现从属地址时。

问题在于,当发布到主实例中时,ROLE命令和INFO输出的复制部分将显示从服务器具有它们用于连接到主服务器的IP地址,而在使用NAT的环境中,可能会比较不同的从实例的逻辑地址(客户端应该用来连接从服务器的地址)。

类似地,从将被列在配置为redis.conf的侦听端口中,在端口被重新映射的情况下,它可能与转发的端口不同。

为了解决这两个问题,从Redis 3.2.2开始,强制一个从设备向主设备通告任意一对IP和端口是可能的。要使用的两个配置指令是:

slave-announce-ip 5.5.5.5
slave-announce-port 1234

并记录在最近Redis发行版的redis.conf示例中。

INFO和ROLE命令

有两个Redis命令可提供有关主从实例的当前复制参数的大量信息。一个是INFO。如果使用复制参数调用该命令作为INFO复制,则只显示与复制相关的信息。另一个更加对计算机友好的命令是ROLE,它提供主和从的复制状态以及它们的复制偏移量,连接的从列表等。

重新启动和故障转移后的部分重新同步

从Redis 4.0开始,当故障转移后将实例升级为主服务器时,它仍然可以与旧主服务器的从服务器执行部分重新同步。为此,从会记住旧主的旧复制ID和偏移量,因此可以将部分积压提供给连接的从服务器,即使它们要求提供旧的复制ID。

但是,提升的从服务器的新复制ID将有所不同,因为它构成数据集的不同历史记录。例如,主服务器可以返回可用,并且可以继续接受写入一段时间,因此在提升的从服务器中使用相同的复制ID会违反复制标识和偏移对中只有一个标识一个数据集的规则。

此外,从设备在关机并重新启动时,能够在RDB文件中存储所需的信息,以便与主设备重新同步。这在升级时很有用。当需要时,最好使用SHUTDOWN命令来执行从服务器的保存和退出操作。

猜你喜欢

转载自blog.csdn.net/heroqiang/article/details/79975742
今日推荐