发布于 2026-01-06 5 阅读
0

冗余和复制:分布式系统中的复制 DEV 的全球展示挑战赛,由 Mux 呈现:展示你的项目!

冗余与复制:分布式系统中的复制

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

在编程领域,我们经常会遇到并参考一些约定俗成的规则、惯例和原则。其中一条原则就是“不要重复自己”(Don't Repeat Yourself,简称 DRY)。我在编程生涯早期就接触到了这个概念,当时觉得它非常简单明了:为了保持代码的简洁性,确保代码库中不重复相同的代码行或逻辑至关重要。

但多年来,我的职业生涯让我学到了更多,也见识了更多,我意识到重复并非总是那么简单——我可不是在开玩笑!有时候,即使冒着过度设计或过度抽象的风险,重复自己也是有意义的。有时候,复制一段功能或逻辑,然后“复制粘贴”到另一个文件中,也是明智之举。

对于分布式系统而言,拥有多个相同的资源往往非常有意义!事实上,当我们开始将“复制”作为分布式计算中的一个概念来审视时,就会越来越清楚地认识到,重复自身实际上可以极大地提升整个系统的性能。因此,让我们深入探讨分布式系统中的复制,并尝试理解我们为什么要这样做。

重复:有时是件好事?

在分布式计算领域,当我们谈到“重复自身”时,其含义可能多种多样。重复一行代码或一段逻辑通常意味着我们存在多个并非真正必要的部分。在分布式系统中,我们用一个专门的术语来描述这种现象,称为冗余,它指的是系统中所有并非系统实际运行所必需的资源。

冗余可以包括哪些内容?

然而,在分布式计算中,我们可能拥有种类繁多的资源,这意味着我们有很多不同的东西可能会重复执行!因此,冗余可以涵盖许多不同类型的额外资源。

例如,系统中不同位置对同一函数的重复调用,或者对同一数据的重复引用/变量,都属于冗余。同样,函数中重复的执行时间以及额外的内存、文件或进程也是冗余的,因为系统实际上并不需要这些重复的资源就能正常运行。

在本系列文章中,我们将重点讨论额外内存、文件或进程方面的冗余,这通常被称为结构冗余。在分布式系统中,额外的内存、文件(例如数据库)或进程都可以抽象成一个我们已经熟悉的术语:节点。

冗余节点:一个定义。

冗余节点是指分布式系统正常运行并非绝对必要的节点。换句话说,任何超出系统基本功能的节点都是多余的,因此我们可以说它是冗余的。

等等——如果我们仔细想想,就会发现分布式系统中存在大量重复数据!在本系列文章中,我们只是粗略地讨论过向系统中添加节点,但我们添加的所有节点并非对系统都是必需的,对吧?那么,我们为什么要添加冗余节点呢?为什么有人会刻意地在系统中引入冗余呢?要真正回答这个问题,我们需要从冗余这个大概念转向更具体的复制问题。

冗余与复制

虽然冗余使我们能够复制系统的组件,但复制本身并不是真正有用的。

如果冗余节点与它所复制的节点不同步,那么冗余实际上对我们没有任何帮助

单独的冗余节点本身作用不大;诚然,我们实现了冗余,但谁又能保证这个冗余节点在我们的系统中能真正发挥作用多久呢?如果其中一个节点的值或状态发生变化,又会发生什么呢?事实证明,这两个问题的答案都是复制!当我们复制系统中的一个节点时,这些副本实际上会变得更加实用。

复制和维护状态

复制的概念与冗余的概念非常相似。两者都涉及在系统中创建冗余节点——这些节点并非系统正常运行所必需。

然而,复制机制在冗余节点的基础上更进一步;它确保冗余节点(副本与其所有其他副本完全相同。乍一看,这似乎很简单,甚至显而易见;我们甚至可以假设从其他地方复制过来的节点与它被复制的源节点完全相同,对吗?

复制节点:定义

嗯,不一定!实际上,假设我们复制了一个节点并创建了一个冗余节点。但之后,我们更改了原始节点的一些内容——例如,更改了它的状态、包含的某个值或某些内部行为。那么冗余节点会发生什么呢?嗯……什么都不会发生!

如果我们只创建一个简单的冗余节点,那么我们的系统中没有任何机制可以确保冗余节点 1) 知道发生了变化,并且 2) 更新自身或被其他人更新,以具有正确的状态。

所以,这个问题或许并不像我们最初想象的那么显而易见!复制机制试图解决这个问题,因为它能确保节点的所有副本彼此完全相同,并且与它们所复制的原始节点完全一致。(顺便一提:如何确保这一点并非易事,我们将在本系列的后续内容中详细探讨……)

这里需要注意的另一点是,复制与透明性密不可分,我们已经 很熟悉这个概念了。每当向系统中添加一个副本时,系统的其余部分都应该继续正常运行,并且理想情况下,它们应该完全不知道已经创建了哪些副本。

如果副本更新,系统的其他部分不应该知道;如果节点被复制,系统的其他部分也不应该关心。

例如,如果Web服务器或数据库节点被复制,分布式系统的最终用户不应该知道自己正在与副本节点还是原始节点交互。(事实上,他们可能根本不应该知道存在复制节点!)

当系统中大部分时间都能保持这种透明度时,复制就能给我们带来诸多好处:

在分布式系统中使用复制的一些好处。

  1. 节点复制使我们的系统更加可靠。如果一个节点发生故障,而我们已经添加了副本,那么副本更有可能接管故障节点的工作。这提高了系统的容错能力。此外,由于有更多备份副本可以随时顶替故障节点,因此也提高了系统的可用性,这意味着系统停机时间不会过长。
  2. 节点复制还能提升系统性能。有了更多副本,我们就能处理更多工作、响应更多请求、处理更多数据。这不仅能提升系统整体速度,降低延迟,还能让系统处理高吞吐量的数据。
  3. 节点复制使我们的系统更容易扩展。可扩展性是构建分布式系统的一大优势,但实现起来并非易事。通过复制更多节点,可以根据系统需求轻松添加更多数据库、服务器或服务来扩展系统。此外,当我们可以将节点复制并部署到不同的洲或国家/地区时,也更容易实现系统的地域扩展,从而帮助扩展特定位置的高负载。

通过复制实现可靠性、性能和可扩展性

到目前为止,我们应该都理解了数据复制的概念(对吧?)。它非常棒,几乎所有分布式系统都会利用这一概念来解决可靠性、性能和容错性方面的问题。无论是工作节点、服务器、数据库还是服务,作为开发人员,我们可能在日常工作中都接触过数据副本!听起来很棒,对吧?

嗯,差不多了。故事还没完全结束。复制技术固然很棒,但它本身也带来了一些独特的挑战。我不能保证在这篇文章里给出任何解决方案(别担心,随着系列文章的深入,我们会详细讨论这个问题),但至少我会向大家介绍其中的一些问题。😉

持续性头痛

除了透明性之外,复制机制要想真正有效运作,还需要另一个要素:一致性。为了确保一个副本与系统中所有其他副本保持同步,它必须与其他副本保持一致。而这绝非易事!

复制操作难在哪里?

乍一看,这似乎并不难。或许我们可以让副本从原始副本获取更新?或者原始副本可以在有其他更改时通知副本?然而,这远比听起来要复杂得多。

由于副本状态会发生变化,因此保持一致性非常困难!

我们之前了解到,要使复制功能正常工作,系统还必须具备透明性。系统透明性意味着所有副本和原始节点必须表现一致,也就是说,系统的使用者(例如最终用户或其他节点)可以向一个副本写入数据,而系统的另一个使用者则可以从另一个副本读取数据!

因此,我们不能再仅仅依赖原始节点作为节点状态的唯一数据源。问题在于,我们如何将刚刚发生的事情告知这两个副本?被读取的副本需要了解最新的写入操作;同样,被写入的副本也需要分发有关该写入操作的信息。

这正是复制如此困难的原因;我们必须兼顾一致性,并找到一种模型来确保所有副本的一致性。好在,我们稍后会更详细地讨论这个问题。现在,我们只需要知道这是一个我们很快就要面对的问题。在此之前,尽情复制你们的小爱心吧!

资源

理解复制和冗余是理解分布式系统如何扩展的关键一步。本系列文章将持续探讨复制的概念,因此充分理解复制至关重要。如果您正在寻找更多资源,以下列出的资源是很好的入门(或继续学习!)之选。

  1. 冗余与复制:系统级容错,库尔特·坎岑巴赫
  2. 分布式系统:复制,于默奥大学
  3. 分布式系统中的复制,Roman Vitenberg
  4. 分布式系统:复制与一致性,Jussi Kangasharju
  5. 理解数据库和分布式系统中的复制,Schiper & Alonso

文章来源:https://dev.to/vaidehijoshi/redundancy-and-replication-duplicating-in-a-distributed-system-p73