分布式存储系统中的一致性和ACID保证

当需要水平缩放以提供增强的性能指标(垂直缩放的系统无法提供足够的资金)时,可以使用分布式系统。

就像从单线程范式到多线程的过渡一样,向分布式系统的迁移需要一种沉浸感,并且要了解它在内部的工作方式,这是您需要注意的。

想要将项目迁移到分布式系统或在其上启动项目的人面临的问题之一就是选择哪种产品。

作为一家在此类系统开发中“ ate之以鼻”的公司,我们帮助我们的客户做出有关分布式存储系统的平衡决策。 我们还发布了一系列网络研讨会,面向更广泛的受众,他们以一种简单的语言关注基本原理,并且任何特定的食物偏好都有助于绘制出重要的特征以使其易于选择。

本文基于我们有关分布式系统中一致性和ACID保证的材料。

它是什么,为什么需要它?


数据 一致性 (有时是数据一致性 )是彼此之间的数据一致性 ,数据完整性和内部一致性。” ( 维基百科

一致性意味着,在任何给定的时间,应用程序都可以确保它们使用的是正确的,技术上相关的数据版本,并且可以在决策时依靠它。

在分布式系统中,确保一致性变得越来越困难和昂贵,因为出现了一系列新挑战,涉及不同节点之间的网络交换,单个节点发生故障的可能性以及(通常)缺少可用于验证的单个内存。

例如,如果我有一个由四个节点组成的系统:A,B,C和D,用于银行交易,并且节点C和D与A和B分开(例如由于网络问题),那么很可能我现在不我可以访问部分交易。 在这种情况下我该怎么办? 不同的系统采用不同的方法。


在顶层,CAP定理表达了两个关键方向。

CAP定理 (也称为Brewer定理 )是一种启发式陈述,在任何分布式计算实现中,最多只能提供以下三个属性中的两个:

  • 数据一致性(Eng。一致性)-在某个时间点的所有计算节点中,数据不会相互矛盾;
  • 可用性(Eng。Availability)-对分布式系统的任何请求均以正确的响应结束,但不能保证系统所有节点的答案都匹配;
  • 分区容限-将分布式系统分为几个独立的部分不会导致每个部分的响应不正确。”

维基百科

当CAP定理讲到一致性时,它意味着一个相当严格的定义,包括记录和读数的线性化,并且在编写单个值时仅规定一致性。 ( 马丁·克莱普曼

CAP定理说,如果我们想抵抗网络问题,那么通常我们必须选择是否要牺牲:一致性或可访问性。 该定理还有一个扩展版本-PACELC( Wikipedia ),它还讨论了以下事实:即使在没有网络问题的情况下,我们也必须在响应速度和一致性之间进行选择。

尽管乍一看是经典DBMS的天生,似乎选择是显而易见的,而一致性是我们拥有的最重要的东西,但事实并非总是如此,这清楚地说明了许多NoSQL DBMS的爆炸性增长,它们做出了不同的选择,并且尽管如此,他们仍然拥有庞大的用户群。 Apache Cassandra具有著名的最终一致性是一个很好的例子。

这完全是由于以下事实:这是一种选择 ,意味着我们要牺牲一些东西,而我们并不总是准备牺牲它。

通常,仅通过放弃这种一致性就可以解决分布式系统中的一致性问题。

但是有必要且重要的一点是,了解何时可以接受这种一致性,以及何时是关键业务需求。

例如,如果我设计一个负责存储用户会话的组件,那么在这里,一致性对我来说并不是很重要,如果仅在有问题的情况下发生数据丢失就不那么重要,这种情况很少发生。 最糟糕的情况是用户将需要登录,并且对于许多企业而言,这对其财务业绩几乎没有影响。

如果我对来自传感器的数据流进行分析,那么在很多情况下,丢失部分数据并在短时间内进行下采样对我来说完全不重要,尤其是当我最终看到数据时。

但是,如果我建立银行系统,现金交易的一致性对我的业务至关重要。 如果我由于没有看到按时还款而对客户的贷款计入罚款,尽管他在系统中,但他却按时付款,这非常非常糟糕。 就像客户可以多次从我的信用卡中提取所有款项一样,这是因为在交易时我遇到了网络问题,并且提取信息没有到达我的集群的一部分。

如果您在网上商店中进行了昂贵的购买,尽管网页上显示成功报告,您也不想忘记您的订单。

但是,如果您选择一致性,则会牺牲可访问性。 通常,这很可能是您个人遇到的不止一次。

如果在线商店的购物篮显示“稍后再试,则分布式DBMS不可用”会比报告成功并忘记订单更好。 最好是由于无法使用银行的服务而拒绝交易,而不是击败成功,然后拒绝银行,因为他忘记了您偿还了贷款。

最后,如果我们研究扩展的PACELC定理,那么我们了解到,即使在系统正常运行的情况下,选择一致性,我们也可以牺牲低延迟,从而可能会降低最高性能。

因此,回答“为什么这是必要的?”这个问题:如果对您的任务而言,拥有最新的,一致的数据非常关键,那么这是有必要的,而替代方案给您带来的重大损失要比事故期间服务暂时无法使用或性能较低。

如何提供呢?


因此,您需要做出的第一个决定是您在CAP定理中的位置,想要在发生事故时保持一致性或可用性。

接下来,您需要了解要在什么级别进行更改。 也许您仅拥有足够的原子记录来影响单个对象,就像MongoDB能够做到的一样(现在它通过对成熟事务的额外支持来扩展了它)。 让我提醒您,CAP定理没有提及涉及多个对象的写操作的一致性:系统很可能是CP(即,更喜欢可访问性一致性),而同时仅提供原子的单个记录。

如果您还不够,我们将开始采用成熟的分布式ACID交易概念。

我注意到,即使进入分布式ACID交易这个勇敢的新世界,我们也经常不得不牺牲一些东西。 例如,许多分布式存储系统具有分布式事务,但是仅在单个分区内。 或者,例如,在没有隔离或隔离级别数量不足的情况下,系统可能不支持所需级别的“ I”部分。

这些限制通常是出于某些原因而做出的:要么简化实现,要么例如提高性能,或者其他原因。 它们足以应付大量案件,因此您不应将它们视为不利因素。

您需要了解这些限制对于您的特定情况是否是一个问题。 如果没有,您将有更多选择,并且可以赋予更多权重,例如,性能指标或系统提供容灾能力等。 最后,我们不要忘记,在许多系统中,根据配置,这些参数可以调整到系统可以是CP或AP的程度。

如果我们的产品旨在成为CP,则通常采用仲裁方法来选择数据,或者使用专用节点作为记录的主要所有者,所有数据更改都将通过它们,并且在网络出现问题的情况下,如果这些主节点无法提供答案是,当外部高度可访问的组件(例如ZooKeeper集群)可以说出哪个集群段是主要的,包含数据的当前版本并可以有效地满足请求时,可以认为原则上无法获得数据或进行仲裁。 秒。

最后,如果我们不仅对CP感兴趣,而且对完全成熟的分布式ACID事务的支持感兴趣,那么通常经常使用单个事实来源,例如集中式磁盘存储,实际上,我们的节点仅充当其缓存,可以在其中禁用提交时间,或应用了多阶段提交协议。

第一个单磁盘方法还简化了实现,降低了分布式事务的等待时间,但以大记录量的负载为代价,以有限的可伸缩性为代价进行交易。

第二种方法在扩展方面提供了更大的自由度,并且又分为两阶段( Wikipedia )和三相( Wikipedia )提交协议。

考虑一个使用例如Apache Ignite的两阶段提交。



提交过程分为两个阶段:准备和提交。

在准备阶段,准备有关准备提交的消息,如果产品认为是必要的话,每个参与者将进行锁定,执行直到实际提交的所有操作,包括实际提交,并将准备发送给其副本。 如果至少有一个参与者由于某种原因拒绝了响应或被证明不可用-数据实际上没有更改,则没有提交。 参与者回滚更改,释放锁定并返回其原始状态。

在提交阶段,提交的实际执行将发送到群集节点。 如果由于某些原因某些节点不可用或有错误响应,那么到那时数据已在其重做日志中输入(因为准备成功),并且无论如何至少可以在挂起状态下完成提交。

最后,如果协调器失败,则在准备阶段将取消提交,在提交阶段可以选择新的协调器,并且如果所有节点均已完成准备,则它可以检查并确保提交阶段已完成。

不同的产品具有自己的实现和优化功能。 因此,例如,某些产品在某些情况下能够将两阶段提交减少为一阶段提交,从而在性能上大获成功。

结论


关键结论:分布式存储系统是一个相当发达的市场,其上的产品可以提供高数据一致性。

此外,该类别的产品位于一致性规模的不同点上,从没有任何交易性的完全AP产品到另外提供全面ACID交易的CP产品。 某些产品可以以一种或另一种方式进行配置。

当您选择所需的内容时,您需要考虑案情的需要,并很好地理解您愿意做出的牺牲和妥协,因为没有什么是免费的,选择其中一个,您很可能会拒绝其他事情。

从这一方面评估产品时,需要注意以下几点:

  • 它们在CAP定理中的位置;
  • 他们是否支持分布式ACID交易?
  • 它们对分布式事务有什么限制(例如,仅在单个分区内等);
  • 使用分布式事务的便利性和效率,将它们集成到其他产品组件中。

Source: https://habr.com/ru/post/zh-CN430852/


All Articles