一文讲透微服务下如何保证事务的一致性

 

1. 从本地事务到分布式事务的演变

什么是事务?回答这个问题之前,我们先来看一个经典的场景:支付宝等交易平台的转账。假设小明需要用支付宝给小红转账 100000 元,此时,小明帐号会少 100000 元,而小红帐号会多 100000 元。如果在转账过程中系统崩溃了,小明帐号少 100000 元,而小红帐号金额不变,就会出大问题,因此这个时候我们就需要使用事务了。请参见图 6-1。

这里,体现了事务一个很重要的特性:原子性。事实上,事务有四个基本特性:原子性、一致性、隔离性、持久性

  1. 原子性,即事务内的操作要么全部成功,要么全部失败,不会在中间的某个环节结束。
  2. 一致性,即使数据库在一个事务执行之前和执行之后,数据库都必须处于一致性状态。如果事务执行失败,那么需要自动回滚到原始状态,换句话说,事务一旦提交,其他事务查看到的结果一致,事务一旦回滚,其他事务也只能看到回滚前的状态。
  3. 隔离性,即在并发环境中,不同的事务同时修改相同的数据时,一个未完成事务不会影响另外一个未完成事务。
  4. 持久性,即事务一旦提交,其修改的数据将永久保存到数据库中,其改变是永久性的。

本地事务通过 ACID 保证数据的强一致性。ACID是 Atomic(原子性)、Consistency(一致性)、 Isolation(隔离性)和 Durability(持久性)的缩写 。在实际开发过程中,我们或多或少都有使用到本地事务。

例如,MySQL 事务处理使用到 begin 开始一个事务,rollback 事务回滚,commit 事务确认。这里,事务提交后,通过 redo log 记录变更,通过 undo log 在失败时进行回滚,保证事务的原子性。笔者补充下,使用 Java 语言的开发者都接触过 Spring。Spring 使用 @Transactional 注解就可以搞定事务功能。事实上,Spring 封装了这些细节,在生成相关的 Bean 的时候,在需要注入相关的带有 @Transactional 注解的 bean 时候用代理去注入,在代理中为我们开启提交/回滚事务。请参见图6-2。

随着业务的高速发展,面对海量数据,例如,上千万甚至上亿的数据,查询一次所花费的时间会变长,甚至会造成数据库的单点压力。因此,我们就要考虑分库与分表方案了。

分库与分表的目的在于,减小数据库的单库单表负担,提高查询性能,缩短查询时间。这里,我们先来看下单库拆分的场景。事实上,分表策略可以归纳为垂直拆分和水平拆分。

垂直拆分,把表的字段进行拆分,即一张字段比较多的表拆分为多张表,这样使得行数据变小。一方面,可以减少客户端程序和数据库之间的网络传输的字节数,因为生产环境共享同一个网络带宽,随着并发查询的增多,有可能造成带宽瓶颈从而造成阻塞。另一方面,一个数据块能存放更多的数据,在查询时就会减少 I/O 次数。

水平拆分,把表的行进行拆分。因为表的行数超过几百万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放。水平拆分,有许多策略,例如,取模分表,时间维度分表等。这种场景下,虽然我们根据特定规则分表了,我们仍然可以使用本地事务。

但是,库内分表,仅仅是解决了单表数据过大的问题,但并没有把单表的数据分散到不同的物理机上,因此并不能减轻 MySQL 服务器的压力,仍然存在同一个物理机上的资源竞争和瓶颈,包括 CPU、内存、磁盘 IO、网络带宽等。

对于分库拆分的场景,它把一张表的数据划分到不同的数据库,多个数据库的表结构一样。此时,如果我们根据一定规则将我们需要使用事务的数据路由到相同的库中,可以通过本地事务保证其强一致性。但是,对于按照业务和功能划分的垂直拆分,它将把业务数据分别放到不同的数据库中。这里,拆分后的系统就会遇到数据的一致性问题,因为我们需要通过事务保证的数据分散在不同的数据库中,而每个数据库只能保证自己的数据可以满足 ACID 保证强一致性,但是在分布式系统中,它们可能部署在不同的服务器上,只能通过网络进行通信,因此无法准确的知道其他数据库中的事务执行情况。请参见图6-3。

此外,不仅仅在跨库调用存在本地事务无法解决的问题,随着微服务的落地中,每个服务都有自己的数据库,并且数据库是相互独立且透明的。那如果服务 A 需要获取服务 B 的数据,就存在跨服务调用,如果遇到服务宕机,或者网络连接异常、同步调用超时等场景就会导致数据的不一致,这个也是一种分布式场景下需要考虑数据一致性问题。请参见图6-4。

总结一下,当业务量级扩大之后的分库,以及微服务落地之后的业务服务化,都会产生分布式数据不一致的问题。既然本地事务无法满足需求,因此分布式事务就要登上舞台。

什么是分布式事务?我们可以简单地理解,它就是为了保证不同数据库的数据一致性的事务解决方案。这里,我们有必要先来了解下 CAP 原则和 BASE 理论。

CAP 原则是 Consistency(一致性)、Availablity(可用性)和 Partition-tolerance(分区容错性)的缩写,它是分布式系统中的平衡理论。在分布式系统中,一致性要求所有节点每次读操作都能保证获取到最新数据;可用性要求无论任何故障产生后都能保证服务仍然可用;分区容错性要求被分区的节点可以正常对外提供服务。

事实上,任何系统只可同时满足其中二个,无法三者兼顾。对于分布式系统而言,分区容错性是一个最基本的要求。那么,如果选择了一致性和分区容错性,放弃可用性,那么网络问题会导致系统不可用。如果选择可用性和分区容错性,放弃一致性,不同的节点之间的数据不能及时同步数据而导致数据的不一致。请参见图 6-5。

此时,BASE 理论针对一致性和可用性提出了一个方案,BASE 是 Basically Available(基本可用)、Soft-state(软状态)和 Eventually Consistent(最终一致性)的缩写,它是最终一致性的理论支撑。简单地理解,在分布式系统中,允许损失部分可用性,并且不同节点进行数据同步的过程存在延时,但是在经过一段时间的修复后,最终能够达到数据的最终一致性。BASE 强调的是数据的最终一致性。相比于 ACID 而言,BASE 通过允许损失部分一致性来获得可用性。

现在,业内比较常用的分布式事务解决方案,包括强一致性的两阶段提交协议,三阶段提交协议,以及最终一致性的可靠事件模式、补偿模式,阿里的 TCC 模式。我们会在后面的章节中详细介绍与实战。

2. 强一致性解决方案

2.1 二阶段提交协议

在分布式系统中,每个数据库只能保证自己的数据可以满足 ACID 保证强一致性,但是它们可能部署在不同的服务器上,只能通过网络进行通信,因此无法准确的知道其他数据库中的事务执行情况。因此,为了解决多个节点之间的协调问题,就需要引入一个协调者负责控制所有节点的操作结果,要么全部成功,要么全部失败。其中,XA 协议是一个分布式事务协议,它有两个角色:事务管理者和资源管理者。这里,我们可以把事务管理者理解为协调者,而资源管理者理解为参与者。
XA 协议通过二阶段提交协议保证强一致性。

二阶段提交协议,顾名思义,它具有两个阶段:第一阶段准备,第二阶段提交。这里,事务管理者(协调者)主要负责控制所有节点的操作结果,包括准备流程和提交流程。

第一阶段,事务管理者(协调者)向资源管理者(参与者)发起准备指令,询问资源管理者(参与者)预提交是否成功。如果资源管理者(参与者)可以完成,就会执行操作,并不提交,最后给出自己响应结果,是预提交成功还是预提交失败。

第二阶段,如果全部资源管理者(参与者)都回复预提交成功,资源管理者(参与者)正式提交命令。如果其中有一个资源管理者(参与者)回复预提交失败,则事务管理者(协调者)向所有的资源管理者(参与者)发起回滚命令。

举个案例,现在我们有一个事务管理者(协调者),三个资源管理者(参与者),那么这个事务中我们需要保证这三个参与者在事务过程中的数据的强一致性。首先,事务管理者(协调者)发起准备指令预判它们是否已经预提交成功了,如果全部回复预提交成功,那么事务管理者(协调者)正式发起提交命令执行数据的变更。请参见图 6-6。

注意的是,虽然二阶段提交协议为保证强一致性提出了一套解决方案,但是仍然存在一些问题。

其一,事务管理者(协调者)主要负责控制所有节点的操作结果,包括准备流程和提交流程,但是整个流程是同步的,所以事务管理者(协调者)必须等待每一个资源管理者(参与者)返回操作结果后才能进行下一步操作。这样就非常容易造成同步阻塞问题。

其二,单点故障也是需要认真考虑的问题。事务管理者(协调者)和资源管理者(参与者)都可能出现宕机,如果资源管理者(参与者)出现故障则无法响应而一直等待,事务管理者(协调者)出现故障则事务流程就失去了控制者,换句话说,就是整个流程会一直阻塞,甚至极端的情况下,一部分资源管理者(参与者)数据执行提交,一部分没有执行提交,也会出现数据不一致性。

此时,读者会提出疑问:这些问题应该都是小概率情况,一般是不会产生的?是的,但是对于分布式事务场景,我们不仅仅需要考虑正常逻辑流程,还需要关注小概率的异常场景,如果我们对异常场景缺乏处理方案,可能就会出现数据的不一致性,那么后期靠人工干预处理,会是一个成本非常大的任务,此外,对于交易的核心链路也许就不是数据问题,而是更加严重的资损问题。

2.2 三阶段提交协议

二阶段提交协议诸多问题,因此三阶段提交协议就要登上舞台了。三阶段提交协议是二阶段提交协议的改良版本,它与二阶段提交协议不同之处在于,引入了超时机制解决同步阻塞问题,此外加入了预备阶段尽可能提早发现无法执行的资源管理者(参与者)并且终止事务,如果全部资源管理者(参与者)都可以完成,才发起第二阶段的准备和第三阶段的提交。否则,其中任何一个资源管理者(参与者)回复执行,或者超时等待,那么就终止事务。总结一下,三阶段提交协议包括:第一阶段预备,第二阶段准备,第二阶段提交。请参见图 6-7。

三阶段提交协议很好的解决了二阶段提交协议带来的问题,是一个非常有参考意义的解决方案。但是,极小概率的场景下可能会出现数据的不一致性。因为三阶段提交协议引入了超时机制,如果出现资源管理者(参与者)超时场景会默认提交成功,但是如果其没有成功执行,或者其他资源管理者(参与者)出现回滚,那么就会出现数据的不一致性。

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
### 回答1: ESD(Electrostatic Discharge,静电放电)是一种瞬时放电现象,通常是由人体或设备上积累的静电电荷引起的。一般来说,ESD会导致电子设备损坏或误操作,因此必须采取措施来避免ESD。 在设计中,ESD保护应该开始于PCB的物理设计。一个好的物理设计将使ESD泄放的能量尽可能地均匀地分散到整个电路板上。这种物理设计包括有效的接地,涂覆和排列PCB层。同时,这也需要考虑到整个系统的电缆结构、机箱接地和隔离等因素,从而最大限度地提高整个系统的耐ESD能力。 此外,在设计电路时,还需要考虑到ESD保护措施。主要的保护措施包括使用可靠的ESD保护器件,如TVS器件、瞬变压抑器和热释电器件,以保护线路免受ESD的影响。此外,在设计输入、输出和供电接口时,还应该采用合适的线路过滤器和电容器,以进一步提高系统的ESD耐受性。 最后,测试是ESD保护设计的重要环节。ESD测试可以验证保护设计的有效性,并排除措施上的缺陷。通常,测试人员会使用标准ESD模拟器来模拟真实的ESD事件。在测试过程中,应注意对设备进行预处理,如去静电和适当的人体模拟。此外,还应该制定合适的检验标准以确保测试的准确性和可重复性。 总之,ESD保护设计至关重要,因为它能够保护电子设备免受静电放电的损害。为了实现可靠的ESD保护,这需要考虑物理设计和电路设计,以及有效的测试工具。最后,只有将所有这些因素合理结合,才能实现有效的ESD保护设计。 ### 回答2: ESD(Electrostatic Discharge,静电放电)指的是在两个带有不同电荷的物体接触或者靠近时,电荷之间发生放电的现象。这种放电可以对各种电子元器件和电路造成损害,从而影响设备的性能和寿命。 ESD的原理可以通过三种方式传递:空气中的放电、直接接触和电感耦合。在实际应用中,ESD对硅芯片、存储器、晶体管等电子元件的损害是非常严重的,这些元件的特性和结构容易受到ESD的影响。 为了防止ESD对电子元件和电路的损坏,需要在设计中采用一些专门的技术,比如在元器件和电路板上增加ESD保护电路、在设备外壳上增加处理工艺等。对于集成电路芯片而言,可以采用对基底和指的进行控制,以及在芯片电路设计过程中合理选择元器件和适当布局等。 总之,ESD保护是电子元器件和电路设计中非常重要的一环,需要采用针对性的技术来减缓和防止ESD对设备的影响,从而保证设备的长期稳定性和可靠性。 ### 回答3: ESD全程为静电放电,是由于静电在两者之间产生的高电压放电引起的电感和电容的相互作用。在现代电子系统中,由于设备的电路越来越小,因此更容易受到静电干扰,人们不得不在设计中考虑如何避免或降低这种静电干扰。本文将从ESD的原理出发,简要介绍如何在电路设计中考虑防止ESD干扰。 ESD的产生是由于静电的积累导致的高电压放电,因此防止ESD干扰的基本原则是减小静电的积累。在电路设计中,静电主要通过两个方面来进行干扰:一是直接放电干扰,即静电直接放电到电路中,导致电路损坏;二是间接放电干扰,即静电放电到设备的金属外壳等部位,导致电磁场干扰影响电路的正常工作。因此,在设计中,需要采用一些措施来减小这些干扰。 1. 选择合适的元器件:在元器件的选择上,要选择一些抗ESD干扰的元器件,如采用ESD保护二极管等,能够减小ESD对电路的影响。 2. 优化电路结构:在电路设计中,要优化电路结构,减少电路间的交叉干扰,避免电路产生高电位差,这样能够减少静电的积累和ESD的辐射。 3. 采用ESD保护电路:在设计电路时,引入一些ESD保护电路,能够有效地减小ESD对电路的影响。例如采用Zener二极管、TVS二极管等保护电路。 在总体设计中,需要综合以上措施,采用一些适合的方案来消除ESD对电路的干扰。同时,在实际使用中,也需要对电路进行定期维护和检测,保证电路的正常运行。在电子技术的快速发展中,ESD防护的问题只会越来越重要,只有对其进行深入的研究和应用,才能更好地保证电子设备的稳定运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值