Redis【有与无】【Admin-3】复制

本文基于Redis 6.0.9版本,前提至少 Redis 3.0或更高版本。

目录

1.复制(Replication)

1.1.当主节点上的持久性关闭时,复制的安全性

1.2.Redis复制是如何工作的

1.3.复制(Replication)ID说明

1.4.无盘复制

1.5.配置 

1.6.Read-only replica

1.7.设置复制节点以对主节点进行身份验证

1.8.只允许写入N个附加复制节点

1.9.Redis复制如何处理键失效

1.10.在Docker和NAT中配置复制

1.11.INFO和ROLE命令

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


1.复制(Replication)

在Redis复制的基础上(不包括Redis Cluster或Redis Sentinel作为附加层提供的高可用性功能),使用和配置领导者跟随者(主从)复制非常简单:它允许副本Redis实例精确主实例的副本。 每当链接断开时,该副本将自动重新连接到主数据库,并且无论该主数据库发生什么情况,它都将尝试作为该副本的精确副本。

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

  1. 当一个主节点和一个复制节点连接良好时,主节点通过向复制节点发送流命令来使复制实例保持更新,以便复制节点对主节点上发生的数据集产生的影响,原因可能有:客户端写入,键已过期,更改主节点数据集的任何其他操作。
  2. 当主节点和复制节点之间的链接断开时,由于网络问题或由于在主节点或复制节点中检测到超时,复制节点将重新连接并尝试进行部分重新同步:这意味着它将尝试获取断开连接期间丢失的部分流命令。
  3. 如果无法进行部分重新同步,则复制节点将要求完全重新同步。 这将涉及一个更复杂的过程,在该过程中,主节点需要创建其所有数据的快照,将其发送到复制节点,然后在数据集更改时继续发送流命令。

默认情况下,Redis使用异步复制(低延迟和高性能)是绝大多数Redis用例使用的复制模式。 但是,Redis 复制节点异步地确认它们与主节点定期接收的数据量。 因此,主节点不会每次都等待复制节点处理命令,但是,如果需要,它知道哪个复制节点已经处理了什么命令。 这允许具有可选的同步复制。

客户端可以使用WAIT命令请求某些数据的同步复制。 但是,WAIT仅能确保其他Redis实例中具有指定数量的已确认复制节点,它不会将一组Redis实例转换为具有高度一致性的CP系统:在故障转移期间,仍然可以丢失已确认的写入,具体取决于Redis持久性的确切配置。 但是,使用WAIT失败事件后丢失写入的可能性大大降低到某些难以触发的失败模式。

你可以查看Sentinel或Redis群集文档,以获取有关高可用性和故障转移的更多信息。 本文档的其余部分主要描述Redis基本复制的基本特征。

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

  1. Redis使用异步复制,异步复制到主节点(replica-to-master)确认处理的数据量。
  2. 一个主节点可以有多个复制节点。
  3. 复制节点能够接受来自其他复制节点的连接。 除了将多个复制节点连接到同一主节点外,复制节点还可以按级联结构连接到其他复制节点。 从Redis 4.0开始,所有子复制节点将从主节点接收完全相同的复制流。
  4. Redis复制在主节点端是无阻塞(non-blocking)。 这意味着当一个或多个复制节点执行初始同步或部分重新同步时,主节点可以继续处理查询。
  5. 复制在复制方面也基本上无阻塞。 当副本执行初始同步时,假设你在redis.conf中配置了Redis,则副本可以使用数据集的旧版本处理查询。 否则,你可以配置Redis副本以在复制流关闭时将错误返回给客户端。 但是,在初始同步之后,必须删除旧的数据集,并且必须加载新的数据集。 副本将在此短暂的窗口内阻止传入的连接(对于非常大的数据集,该连接可能长达数秒)。 从Redis 4.0开始,可以对Redis进行配置,以使旧数据集的删除发生在不同的线程中,但是加载新的初始数据集仍将在主线程中发生并阻止副本。
  6. 复制既可以用于可伸缩性,也可以用于只读查询的多个复制节点(例如,可以将慢速的 O(N) 操作卸载到复制节点中),或者仅用于提高数据安全性和高可用性。
  7. 可以使用复制来避免让主节点数据库将整个数据集写入磁盘的成本:一种典型的技术涉及配置你的主节点的redis.conf文件,以避免完全保留到磁盘,然后连接配置为不时保存或启用AOF的复制节点。 但是,必须谨慎处理此设置,因为重新启动的主节点将以空数据集开始:如果复杂节点尝试与其同步,则复杂节点也将被清空。

1.1.当主节点上的持久性关闭时,复制的安全性

在使用Redis复制的设置中,强烈建议在主节点数据库和复制节点数据库中启用持久性。 如果不可能(例如,由于磁盘速度非常慢而导致延迟问题),则应将实例配置为避免重启后自动重启

为了更好地理解配置为自动重新启动的持久性已关闭的主节点服务器为何具有危险性,请检查以下故障模式,在该故障模式下会从主节点及其所有复制节点中擦除数据:

  1. 我们有一个设置,其中节点A充当主节点,而持久性已关闭,并且节点B和C,从节点A复制过来。
  2. 节点A崩溃,但是它具有一些自动重新启动系统,该系统可以重新启动进程。 但是,由于关闭了持久性,因此节点将使用空数据集重新启动。
  3. 节点B和C将从为空的节点A复制过来,因此它们将有效地销毁它们的复制数据。

当使用Redis Sentinel来实现高可用性时,关闭主节点上的持久性以及自动重启该过程也是很危险的。 例如,主节点可以足够快速地重新启动,以使Sentinel无法检测到故障,从而发生上述故障模式。

每当数据安全性很重要,并且复制与配置了持久性的主节点一起使用时,都应禁用实例的自动重启。

1.2.Redis复制是如何工作的

每个Redis主节点数据库都有一个复制ID:这是一个较大的伪随机字符串,用于标记给定存储(story)的数据集。

每个主节点还采用一个偏移量,该偏移量会针对复制流中要发送到复制节点的每个字节的增量而增加,以便使用修改数据集的新更改来更新复制节点的状态。 即使实际上未连接任何复制节点,复制偏移也会增加,因此基本上每个给定的一对:

Replication ID, offset

标识主节点数据集的确切版本。

当复制节点连接到主节点数据库时,它们使用PSYNC命令来发送其旧的主节点复制ID和(到目前为止)已处理的偏移量。 这样主节点可以只发送所需的增量部分。 但是,如果在主节点缓冲区中,没有足够backlog,或者复制节点引用的历史记录(复制ID)不再已知,则会发生完全重新同步:在这种情况下,复制节点将从头开始获得完整复制的数据集。

完整同步的工作方式如下:

主节点开启一个后台保存进程,以产生RDB文件。 同时,它开始缓冲从客户端收到的所有新写命令。 当后台保存完成后,主节点将数据库文件传输到复制节点,复制节点将其保存在磁盘上,然后将其加载到内存中。主节点将所有缓冲的命令发送到复制节点。 这是作为流命令完成的,并且与Redis协议本身的格式相同。

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

如前所述,当主节点与复制节点链接出于某种原因断开时,复制节点能够自动重新连接。 如果主节点收到多个并发的复制节点的同步请求,它将执行一次后台保存,以便为所有请求提供服务。

1.3.复制(Replication)ID说明

在上一节中,我们说过,如果两个实例具有相同的复制ID和复制偏移,则它们具有完全相同的数据。 但是,了解复制ID到底是什么以及为什么实例实际上具有两个复制ID(主要(main )ID和辅助(secondary )ID)很有用。

复制ID基本上标记了数据集的给定历史记录。 每次实例作为主节点从头重新启动时,或将复制节点提升为主节点时,都会为此实例生成一个新的复制ID。握手后,连接到主节点的复制节点将继承其复制ID。 因此,具有相同ID的两个实例通过以下事实相关联:它们拥有相同的数据,但可能在不同的时间。 对于拥有最新数据集的给定历史记录(复制ID),这是理解逻辑时间的偏移量。

例如,如果两个实例A和B具有相同的复制ID,但是一个实例的偏移量为1000,而另一个实例的偏移量为1023,则意味着第一个实例缺少应用于数据集的某些命令。 这也意味着,通过仅应用一些命令,A可能会达到与B完全相同的状态。

Redis实例具有两个复制ID的原因是由于将复制节点提升为主节点。 故障转移之后,升级后的复制节点仍需要记住其过去的复制ID,因为该复制ID是以前的主节点之一。 这样的话,当其他复制节点将与新的主节点同步时,它们将尝试使用旧的主节点ID来执行部分重新同步。 这将按预期工作,因为将复制节点提升为主节点时,它会将其辅助(secondary )ID设置为其主(main)ID,并记住发生此ID切换时的偏移量。 稍后它将选择一个新的随机复制ID,因为新的历史记录开始了。 处理连接的新的复制节点时,主节点将其ID和偏移量与当前ID和辅助ID匹配(为安全起见,直到给定的偏移量)。 简而言之,这意味着在故障转移之后,连接到新提升的主节点的复制节点无需执行完全同步。

在故障转移后,为什么复制节点提升为主节点需要更改其复制ID?

答:由于某些网络分区,旧主节点可能仍在作为主节点使用,并且保留相同的复制ID会违反以下事实(任何两个随机实例具有相同的ID和相同的偏移量意味着它们具有相同的数据集)

1.4.无盘复制

通常,完全重新同步需要在磁盘上创建RDB文件,然后从磁盘重新加载相同的RDB,以便为复制节点提供数据。

对于慢速磁盘,这对于主节点而言可能是非常压力的操作。 Redis 2.8.18版是第一个支持无盘复制的版本。 在此设置中,子进程直接通过线路将RDB发送到复制节点,而无需使用磁盘作为中间存储。

1.5.配置 

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

replicaof 192.168.1.1 6379

当然,你需要用主节点IP地址(或主节点名)和端口替换192.168.1.1 6379。 或者,你可以调用REPLICAOF命令,并且主节点将开始与复制节点同步。

还有一些参数可用于调整主节点在内存中执行的复制backlog,以执行部分重新同步。 有关更多信息,请参见Redis分发随附的示例redis.conf。

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

1.6.Read-only replica

从Redis 2.6开始,复制节点(replica)支持默认情况下启用的只读模式。 此行为由redis.conf文件中的只读复制节点(replica)选项控制,并且可以在运行时使用CONFIG SET启用和禁用。

只读复制节点将拒绝所有写入命令,因此由于错误而无法写入复制节点。 这并不意味着该功能旨在将复制节点实例公开给Internet,或更普遍地公开给存在不受信任客户端的网络,因为仍启用了DEBUG或CONFIG之类的管理命令。 但是,可以通过使用rename-command指令禁用redis.conf中的命令来提高只读实例的安全性。

你可能想知道为什么可以还原只读设置并具有可被写操作作为目标的复制节点实例。 尽管如果复制节点和主节点重新同步或复制节点重新启动,这些写操作将被丢弃,但是有一些合法的用例将临时数据存储在可写复制节点中。

例如,计算慢速 Set或Sorted set 操作并将其存储到本地键中是多次观察到的可写复制节点的用例。

但是请注意,版本4.0之前的可写复制节点无法使(具有生存时间的)键到期。 这意味着,如果你使用EXPIRE 或其他为某个键设置最大TTL的命令,则该键会泄漏,并且当你使用读取命令访问它时可能不再看到它时,你会在键的计数中看到它仍会使用内存。 因此,通常将可写复制节点(4.0版之前的版本)和键与TTL混合会造成问题。

Redis 4.0 RC3和更高版本完全解决了此问题,现在可写副本能够像主服务器一样使用TTL驱逐键,但以DB编号大于63写入的键除外(但默认情况下,Redis实例只有16个数据库)。

还要注意,由于Redis 4.0 复制节点仅在本地写入,不会传播到附加到实例的子复制节点(Sub-replicas)。 子复制节点(Sub-replicas)将始终接收与顶级主节点发送给中间复制节点的复制流相同的复制流。因此,例如在以下设置中:

A ---> B ---> C

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

1.7.设置复制节点以对主节点进行身份验证

如果你的主节点数据库通过requirepass拥有密码,那么配置复制节点以在所有同步操作中使用该密码很简单。

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

config set masterauth <password>

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

masterauth <password>

1.8.只允许写入N个附加复制节点

从Redis 2.8开始,可以将Redis主节点配置为仅在当前至少有N个复制节点连接到该主节点时才接受写查询。

但是,由于Redis使用异步复制,因此无法确保复制节点实际上收到了给定的写操作,因此始终存在数据丢失的窗口。

该功能的工作方式如下:

  • Redis复制节点每秒对主节点进行一次ping操作,确认已处理的复制流数量。
  • Redis的主节点会记得上一次它收到每个复制节点的ping命令。
  • 用户可以配置滞后不大于最大秒数的最小复制节点数。

如果至少有N个复制节点,并且延迟少于M秒,则将接受写入。

你可能会认为它是尽力而为的数据安全机制,其中不能确保给定写入的一致性,但是至少将数据丢失的时间窗限制为给定的秒数。 通常,绑定数据丢失比未绑定数据丢失更好。

如果不满足条件,则主节点将返回一个错误,并且将不接受写入。

此功能有两个配置参数:

  • min-replicas-to-write <number of replicas>
  • min-replicas-max-lag <number of seconds>

有关更多信息,请检查Redis源分发包随附的示例redis.conf文件。

1.9.Redis复制如何处理键失效

Redis过期使键具有有限的生存时间(TTL)。 这种功能取决于实例计算时间的能力,但是Redis复制节点正确复制带有过期的键,即使使用Lua脚本更改了此类键也是如此。

要实现这种功能,Redis不能依赖于主节点和复制节点具有同步时钟的能力,因为这是一个无法解决的问题,将导致竞争状况和数据集差异,因此Redis使用三种主要技术来使过期键的复制能够正常工作:

  1. 复制节点不会使键失效,而是等待主节点使键失效。 当主节点使键过期(或由于LRU而将其退出)时,它会合成DEL 命令,该命令将传输到所有复制节点。
  2. 但是,由于主节点驱动的过期,有时复制节点可能仍在逻辑上已过期的内存键中,因为主节点无法及时提供DEL命令。 为了解决这个问题,复制节点使用它的逻辑时钟来报告一个键,该键仅用于不违反数据集一致性的读取操作(因为将收到来自主节点的新命令)。 这样,复制节点可以避免报告逻辑上已过期的键仍然存在。 实际上,使用复制节点进行缩放的HTML片段缓存将避免返回早于所需生存时间的项目。
  3. 在Lua脚本执行期间,不会执行任何键过期。 当Lua脚本运行时,从概念上讲,主节点中的时间被冻结,因此给定的键在脚本运行的所有时间内都将存在或不存在。 这样可以防止键在脚本中间过期,并且这是将键发送到复制节点以确保在数据集中具有相同效果所必需的。

将复制节点提升为主节点后,它将独立开始失效键,并且不需要其旧主节点的任何帮助。

1.10.在Docker和NAT中配置复制

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

问题在于,当发布到主节点实例中时,ROLE命令和INFO输出的复制部分,会显示为具有其用于连接到主节点的IP地址的复制节点 ,而在使用NAT的环境中,对比复制节点实例的逻辑地址,可能会有所不同 (客户端应用于连接复制节点的逻辑地址)。

类似地,复制节点将列出,侦听端口配置为redis.conf,如果重新映射端口,则该复制节点可能与转发端口不同。

为了解决这两个问题,自Redis 3.2.2起,可以强制复制节点向主节点声明任意IP和端口对。 要使用的两个配置指令是:

replica-announce-ip 5.5.5.5
replica-announce-port 1234

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

1.11.INFO和ROLE命令

有两个Redis命令可提供有关主节点实例和复制节点实例的当前复制参数信息。

  • INFO  如果使用replication参数作为INFO replication调用该命令,则仅显示与复制相关的信息。
  • ROLE 它提供了主节点和复制节点的状态以及它们的复制偏移量,已连接复制节点的列表等。

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

从Redis 4.0开始,在故障转移后将实例提升为主节点时,它仍将能够与旧主节点的复制节点执行部分重新同步。 为此,复制节点会记住旧的复制ID及其以前的主节点的偏移量,因此即使连接的复制节点要求使用旧的复制ID,也可以将部分积压提供给连接的复制节点。

但是,升级复制节点的新复制ID将有所不同,因为它构成了数据集的不同历史记录。 例如,主节点可以返回可用状态,并且可以继续接受写入一段时间,因此在升级复制节点中使用相同的复制ID将违反复制ID和偏移对a仅标识单个数据集的规则。

此外,复制节点(在轻轻关闭电源并重新启动后)能够将所需的信息存储在RDB文件中,以便与主节点重新同步。 这在升级时很有用。 必要时,最好使用SHUTDOWN 命令对复制节点执行save & quit 操作。

无法部分重新同步通过AOF文件重新启动的复制节点。 但是,可以在关闭实例之前将实例转换为RDB持久性,然后再重新启动,最后可以再次启用AOF。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

琴 韵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值