重载系统中的数据一致性

发行


几乎任何信息系统都需要持续存储数据。 在大多数中小型负载的系统中,此功能由关系DBMS执行,其无可争议的优势是可以保证数据的一致性。

一个解释数据一致性是什么的经典示例-将资金从一个帐户转移到另一个帐户的操作。 当更改一个帐户余额的操作已经完成而另一个帐户还没有时间时,可能会发生故障。 然后,资金将从一个帐户中扣除,但不会记入另一个帐户。 系统数据的这种状态称为不一致,也许不需要解释这可能导致什么后果。 关系DBMS提供了一种事务处理机制,可确保在任何给定时间的数据一致性。 事务是将一个一致状态转移到另一个一致状态的有限操作集。 如果任何步骤发生错误,DBMS都会取消所有先前执行的操作,并将数据返回到其原始同意状态。 换句话说,将执行所有操作,或者不执行单个操作。

对于大型系统,由于负载太重,在其中始终无法使用单个数据库。 在这种情况下,每个系统模块(服务)都具有自己的单独数据库。 在这种情况下,出现了一个问题,即如何确保此类集群体系结构的数据一致性。

解决数据一致性


一种解决方案是分布式事务。 首先,集群的所有节点必须同意该操作是可能的,然后将更改提交给所有节点。 由于节点没有公用存储设备,因此,达成共识的唯一方法是使用某种分布式共识协议进行协商。

捕获全局事务的简单协议是两阶段提交(2PC)。 执行事务的节点被视为协调器。 在准备阶段(准备),协调器将事务提交通知其他节点,并等待其他节点确认它们已准备好提交。 如果至少一个节点尚未就绪,则事务中断。 在提交阶段,协调器通知所有节点提交事务的决定。 收到所有人的确认,一切都很好后,协调器还将捕获交易。

图片

图1-两阶段提交的一般方案


该协议避免了最少的消息,但是不够健壮。 例如,如果协调器在准备阶段之后失败,则其余节点不具有有关是否应提交或取消事务的信息(它们将不得不等待修复错误)。 2PC(以及其他分布式事务协议,例如3PC)的另一个严重缺陷是,随着群集节点数量的增加,两阶段提交的性能会下降。

图片

图2-两站提交速度与DBMS集群中服务器数量的关系


另外,分布式事务处理方法有一个局限性:系统的所有模块必须使用相同的DBMS,这并不总是很方便。

另一个选择是提供一种机制,使您可以将不同的数据库(用于服务)作为单个数据库使用(以解决分布式数据库中的数据完整性问题)。 同时,需要某种分布式系统交易(“业务交易”)的类似物。

在普通事务以及两阶段提交中,所有操作都由事务机制控制(使用锁),这样做是为了提供回滚任何操作的能力(悲观方法-我们认为任何操作都可能导致失败)。 这是系统的瓶颈。 一种替代方法是所谓的乐观方法:我们认为大多数操作都可以成功完成。 如果发生故障,我们还将执行其他操作。 即 降低大多数操作的成本,从而提高生产率。

什么是传奇,它如何运作


Saga是微服务架构事务的替代方法。 Saga(saga)是由系统的各个模块(服务)执行的一组步骤; 此外,还需要佐贺服务,该服务负责整个操作(业务交易)。 步骤通过事件图链接。 传奇完成后,系统必须从一个同意的状态进入另一状态(如果成功执行),或者必须返回到先前的同意状态(如果取消)。

如何实现这种业务交易的退回或回退? 为此,传奇使用了取消步长(补偿动作)的机制。 例如,步骤之一成功(例如,一个条目已添加到用户数据库表中),但以下步骤之一失败,因此应取消整个传奇。 然后,同一服务会收到命令-取消操作。 但是在服务DBMS中,本地事务已经完成,用户记录已添加。 然后,要返回到先前的状态,服务必须执行补偿操作(在我们的示例中,删除记录)。 取消步骤允许在传奇的框架内实现原子性(“全有或全无”)-所有步骤均已执行或得到补偿。

图片

图3-Saga的工作机制和补偿效应的性质


在图3中,将传奇的步骤指定为T1 ... T4,以补偿动作:C1 ... C4。
Sagas支持步骤的幂等(重复重复的操作等效于一个操作)。 垂度方法提供了重复任何步骤的机会(例如,如果您未收到成功完成的响应)。 幂等性还允许您在任何节点上的数据丢失(故障和恢复)时恢复状态。 在执行步骤时,每个服务应(通过幂等性键)确定它是否已经执行了此步骤(如果未执行,则执行,否则跳过)。 为了补偿动作,还可以添加幂等键和操作重复(确保持久性/稳定性)。

总结


在ACID交易系统的四个要求(原子性,一致性,隔离性,稳定性)中,下垂机制允许实现三个-除隔离性之外的所有其他条件。 缺乏隔离会导致异常(“脏读”,“不可重复读”,重写不同业务交易之间的变更等)。 为了克服这种情况,需要使用其他机制,例如,可变对象的版本控制。

Sagas可让您解决以下任务:

  • 为业务关键数据提供相关数据更改;
  • 能够设置严格的步骤顺序;
  • 符合100%的一致性(即使发生事故也可提供坐标数据);
  • 提供所有级别的性能检查。

范围和应用示例


Sagas通常用于具有大量请求的系统。 例如,流行的电子邮件服务,社交网络。 但是,该方法可能会在较小规模的项目中找到应用。

我们公司在为大型企业开发会计系统方面有丰富的经验,该系统是为几十个用户设计的,所有数据都存储在一个关系DBMS中。 在实现计划工作的自动计算时出现了问题:在某些情况下,计算量很大,并且需要在DBMS表中插入数百万条记录,这极大地加载了DBMS,并减慢了整个系统的运行速度。

找到了一个解决方案-使用自己的DBMS将工作计算逻辑放入一个单独的服务中,用于存储工作本身和相关对象。 传奇确保了数据的一致性。 如果计算失败,则应用程序的主模块会收到命令以取消逻辑计算操作。

支持Saga的库


该应用程序是在.Net上开发的,针对该技术,有多个支持sagas的服务管理器库。 我们研究了NServiceBus,MassTransit和Rebus库。 结果,我们选择了Rebus-该库更易于学习,同时完全实现了sagas的原理并且可以免费使用。 NServiceBus和MassTransit是具有许多附加功能的更复杂的工具。 它们不是我们任务的一部分,但建议在以后的逻辑更复杂的项目中使用它们。

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


All Articles