严格一致性是主存储的硬性要求

Strict Consistency is a Hard Requirement for Primary Storage

企业依靠数据来做出决策。有效的决策制定依赖于数据的准确性、及时性、可用性和安全性。数据一致性是购买存储时不可忽视的重要因素,它涉及确保所有相关方在数据库事务完成(通过提交或回滚)后,能够立即访问到事务的结果。这保证了所有访问数据的用户都能同时看到相同的信息,并且信息可靠、有用且不损坏。因此,数据一致性在基于事务的环境中至关重要。

对象存储的出现

近年来,结构化、半结构化和非结构化数据激增。我们还见证了云原生、非关系型数据库和数据湖仓库(例如 Apache IcebergApache HudiDelta Lake)的兴起,它们是传统关系型数据库的替代方案。这些技术与对象存储相结合,提供了一种简化的数据存储和访问方式,消除了许多由专有 RDBMS 造成的约束。各行各业纷纷采用对象存储和非关系型数据库架构,因为它们共同提供了关系型数据库无法最佳实现的一系列功能,例如大规模下的卓越性能、由于容器化和 Kubernetes 带来的高可用性,以及由于 S3 API 对所有应用程序开放而实现的高扩展性。

随着架构适应这些现代数据处理方法,对象存储由于其性能、可扩展性和持久性而取代了传统的文件和块存储。企业界争先恐后地投入使用对象存储,因为这项技术带来了响应时间、可扩展性、可用性和容错性的改进。S3 API 的简洁性和存储在系统中的对象的扁平结构对企业很有吸引力,因为它们提高了开发人员的生产力和代码可移植性。  

然而,对象存储的广泛采用也带来了新的挑战,特别是数据一致性问题,这是关系型数据库供应商几十年前就解决的问题。对于企业数据系统中的数据,首席信息官、首席信息安全官和首席技术官必须了解选择最终一致性或强一致性的影响。

什么是严格一致性或强一致性? 

在任何高并发云系统中,任何数据的多个副本都可能存在于不同的物理位置,包括公有云和本地,以及各种微服务和容器中。让我们花点时间以一个在线零售的例子来深入探讨一致性。 

假设一家网络零售商使用对象存储构建了一个库存管理系统。当一名员工签出商品准备发货,而另一名员工同时登录记录从制造商处收到了一箱新商品时会发生什么?他们会尝试同时更新 S3 中的同一个对象(同一个键)。那么,当运行查询时会发生什么? 

在严格一致性系统中,库存将始终保持准确。在最终一致性系统中,读取陈旧数据可能会导致超卖或少卖。

软件工程师在开发应用程序时,必须就所需的一致性级别做出重要决定,并且必须考虑到在不同平台上呈现一致信息的必要性。他们确保库存信息在任何地方都保持一致的唯一方法是在健壮的数据安全、持久性和一致性基础上构建应用程序。

强数据一致性保证数据始终保持准确,这在当今的企业中非常重要。但是,需要考虑一些权衡,特别是在系统性能和用户体验方面。强一致性可能存在一个潜在的缺点,因为除非系统设计得当,否则它会导致整体系统性能下降,从而对用户体验产生负面影响。例如,当客户试图使用强一致性系统购买商品时,即使库存五秒钟前通过事务更新过,并且很可能准确,他们也可能无法立即执行事务。但在最终一致性系统中,客户可以购买商品,这可能会导致超卖。强一致性不是“极有可能”,而是“绝对确定”。 

过去,构建一个能够平衡性能和一致性的系统更容易,因为规模和地理位置无关紧要,因为系统都是本地部署的。对于运行在单个节点上的 RDBMS 或具有两个到四个节点的分布式数据库来说,这比较简单,但在具有数十个全球数据节点的多云计算环境中,复杂性会大大增加。这个问题在云架构中变得尤为重要,因为网络延迟和可靠性会进一步影响性能,严重影响响应时间、可扩展性和可用性。

最终一致性的宽松性

由于强一致性难以实现,存储和数据库开发人员选择通过后退一步,开发最终一致性来“解决”与强一致性相关的性能和可用性问题。放弃了立即实现强一致性的现实,最终一致性理论上保证,只要没有对数据进行新的更新,所有对该数据的未来读取最终都会返回最近更新的值。

在最终一致性框架中,数据的副本可能并不总是完全相同,但它们被设计成最终收敛并保持一致,只要所有正在进行的操作都已处理完毕。例如,域名系统 (DNS) 使用最终一致性模型。

DNS 服务器以不及时更新而闻名。单个 DNS 服务器可能难以始终提供最新地址信息;相反,值被缓存并分布在互联网周围的众多分层目录中。将修改后的值传播到所有 DNS 客户端和服务器需要一些时间——最佳做法是不期望您的更改在不到三天的时间内传播到全球。但是,DNS 系统非常成功,并且是互联网的基础设施组件。DNS 系统以其高可用性和全球可扩展性而著称,它为整个互联网超过一亿台设备提供名称查找服务。

这与前面提到的在线零售库存示例形成鲜明对比。在最终一致性数据模型中,即使库存应用程序和数据当前不可用于查询,购物应用程序也会在移动设备上显示最新的商品库存,如果它被编程地判定为最新且合理可靠。最终一致性不是我想要用来购物的方式,因为我希望得到一些保证,确保我购买的商品有货且可用。最终一致性对于 Facebook 状态来说是可以的,但对于任何与交易稍微沾边的东西来说都不合适。

为什么?

一致性的大辩论

强一致性支持者和最终一致性支持者之间的辩论几乎与计算本身一样古老。选择采用哪一种与 CAP 定理 紧密相关,该定理指出,分布式数据存储无法同时确保以下三项保证:

  1. 一致性
  2. 可用性
  3. 分区容忍性

让我们用一个例子来深入了解。在多云环境中,在构建分布式数据和云基础设施时,网络分区相当频繁。在这种情况下,解决方案架构师需要决定是优先考虑数据可用性还是数据一致性。两种一致性模型都强调其中一项而不是另一项。需要注意的是,最终一致性并没有完全消除一致性。相反,它建议暂时放宽数据一致性,以确保数据在一段时间内可用。还需要注意的是,最终一致性中的“最终”从未由依赖它的对象存储供应商定义——最终一致性是几毫秒、几秒钟还是几天?

做出一致性决策

云架构师不能选择错误的数据一致性模型。强一致性和最终一致性模型都是有价值的工具,但每个架构师都必须在具体情况下仔细评估和选择最合适的模型。必须认识到,最终一致性不是强一致性的替代品,而是解决不同业务用例的不同方法。

对于涉及大量数据记录的情况,例如 Facebook 状态,最终一致性可能更受欢迎。在查询结果产生大量数据的情况下,最终一致性非常适合,更重要的是,用户体验可能不会显著地依赖于单个实体的具体包含或排除。相反,在单个上下文中包含有限数量的实体的情况表明需要强一致性。在这种情况下,用户体验必须与数据的上下文和用例保持一致。 

如果数据经常发生变化,最终一致性可能不是合适的选择。用户必须等待更改传播到多云中的所有副本,然后查询才能返回最新版本。因此,最终一致性更适合于数据相对稳定的传统对象存储用例,例如备份、存档、视频和音频文件、虚拟机 (VM) 映像和工件。

为什么并非所有对象存储都严格一致?

事实证明,构建一个提供强一致性的、大规模可扩展的分布式对象存储系统并非易事,问问 AWS 他们在 改进最初的最终一致性 S3 时遇到了多大的困难。

查看这篇博文可以深入了解为什么其他对象存储供应商在构建像 AWS S3 和 MinIO 这样的解决方案的严格一致性方面遇到如此大的困难。

作者非常明确地说明了这一点:“我们希望强一致性无需额外成本,适用于所有新旧对象,并且不影响性能或可用性。

AWS 不想效仿“其他提供商 [他们] 做出妥协,例如将强一致性作为存储桶或帐户的可选设置,而不是所有存储的可选设置”。他们知道,作为云对象存储的领导者,他们不能仅靠口头支持一致性而蒙混过关。其他供应商却没有那么坦诚。

为了向 AWS 添加强一致性,他们意识到他们必须首先使元数据缓存具有强一致性,而这在 S3 的规模上将是一项“艰巨的任务”。他们最近发布了新的复制逻辑,这成为他们缓存一致性协议的核心部分。他们还添加了一个“见证者”组件,以防止读取操作,直到系统能够验证缓存中的对象不是陈旧的。如果它不是陈旧的,那么将提供缓存的版本;如果它已陈旧,那么将使缓存失效,并从持久层提供对象。

该团队知道,缓存一致性协议不容出错,而且他们需要在不影响 S3 的性能和可用性的情况下完成这项任务。

该团队在验证方面也投入了比实际实现本身更多的周期。“重要的是要正确实现强一致性,这样就不会出现破坏一致性的边缘情况。”然而,S3 是一个庞大的分布式系统,拥有众多用户,并且不可避免地会遇到边缘情况。“即使某个事件仅在十亿次请求中发生一次,这意味着它每天在 S3 中都会发生多次。”

使用 MinIO 构建强一致性

MinIO 在分布式和独立模式下对所有 I/O 操作遵循严格的写后读和写后列出的一致性模型。这意味着,在成功写入新对象或覆盖或删除现有对象后,所有后续读取请求将立即返回对象的最新版本。当您使用磁盘文件系统(如 XFS、ZFS 或 BTRFS)进行分布式设置时,可以保证此一致性模型。避免将 MinIO 部署到 EXT4 和 NFS。

MinIO 确保一旦写入操作被确认成功,应用程序就可以对该对象执行操作,例如 LIST。这种强一致性保证对于需要数据准确性和可靠性的应用程序(如分析和 ML)至关重要。如果没有这种内置的强一致性,您的团队将需要付出大量工作来构建他们需要的应用程序,同时还要构建应用程序来测试一致性。

MinIO 旨在为分布式环境提供强数据一致性。以下是 MinIO 如何实现这一点:

ACID 事务:MinIO 采用 ACID(原子性、一致性、隔离性、持久性)事务来确保强一致性。当多个客户端或应用程序执行并发读写操作时,MinIO 确保这些操作以维护数据一致性的方式执行。

锁定机制:MinIO 使用锁定机制在写入操作期间控制对对象的访问。当一个客户端写入对象时,其他客户端将被阻止访问该对象,直到写入操作完成。这确保了对象更新在写入成功之前对其他客户端不可见。

版本控制:MinIO 支持对象的版本控制,这意味着对对象的每次更新都会创建该对象的新版本。这允许对对象进行时间点访问,并维护更改的完整历史记录,这对于审计和数据完整性目的非常有用。

分布式架构:MinIO 旨在用于分布式和高可用性架构。它可以在多个节点或数据中心部署,并使用诸如基于仲裁的复制等机制来维护数据一致性,即使面对网络分区和硬件故障也是如此。

主存储严格一致

对象存储是一个将数据分散到许多节点上的分布式系统,它过去依赖于最终一致性来克服性能挑战。这种传统的設計選擇使得傳統的对象存储适用于存档大型文件、保存备份和存储视频和音频文件,但当针对要求苛刻的现代分析和 AI/ML 工作负载部署对象存储时,它是不可接受的。不知道应用程序是否正在使用最新且有效的數據可能会造成一些真正的麻烦,比如丢失事务和客户数据损坏。

MinIO 确保数据更新在所有副本中一致地反映出来,并且一旦确认写入操作,所有后续读取都将返回更新后的数据,这使其成为需要强数据一致性的应用程序的绝佳选择,特别是在对象存储用作主存储的情况下。

您可以 此处 下载 MinIO。如果您有任何问题,请在 hello@min.io 上联系我们,或加入 Slack 社区