当前位置: 首页 > 后端技术 > Java

分布式事务(一)——分布式事务的概念

时间:2023-04-02 02:02:54 Java

当今的互联网世界,分布式系统和微服务架构盛行。一个简单的操作很可能由服务器端的多个服务和数据库实例来完成。在互联网金融等对一致性要求较高的场景中,多个独立操作之间的一致性问题尤为棘手。随着业务的快速发展和业务的日益复杂,几乎每个公司的系统都会从单体走向分布式,尤其是走向微服务架构,进而不可避免地会遇到分布式事务的问题。本文将介绍分布式事务的一些相关概念。分布式事务的概念数据库事务数据库事务的目的数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单元,由有限的数据库操作序列组成。数据库事务通常由一系列对数据库的读/写操作组成。包含以下两个目的:提供数据库操作序列从故障状态恢复到正常状态的方法,提供数据库即使在异常状态下也能保持一致性的方法。当多个应用程序并发访问数据库时,可以在这些应用程序之间提供隔离的方法,防止彼此的操作相互干扰。当事务提交给数据库管理系统(DBMS)时,DBMS需要确保事务中的所有操作都成功完成,并将结果永久存储在数据库中。如果事务中的某些操作没有成功完成,事务中的所有操作都需要回滚到事务执行前的状态;同时,该事务对数据库或其他事务的执行没有任何影响,所有事务似乎都在独立运行。ACID特性数据库事务有以下四个特性,习惯上称之为ACID特性:原子性(Atomicity):一个事务中的所有操作都像一个原子一样不可分割地作为一个整体,要么全部成功,要么全部失败。一致性:事务的执行结果必须使数据库从一种一致状态进入另一种一致状态。状态一致是指:1.系统的状态满足数据的完整性约束(主码、参照完整性、校验约束等)2.系统的状态反映了现实世界的真实状态数据库应该描述,如两个事务传输前后。每个帐户中的金额总和应保持不变。隔离性:并发执行的事务互不影响,对数据库的影响与串行执行的相同。比如多个用户同时向一个账户转账,那么最终账户的结果应该和他们依次转账的结果是一样的。持久性:一旦事务被提交,它对数据库的更新是持久的。任何事务或系统故障都不会导致数据丢失。数据库的并发控制有两个因素影响数据库中ACID的实现:并发度和系统故障。相应的,数据库系统通过并发控制技术和日志恢复技术来实现数据库的ACID特性。并发控制技术是实现事务隔离和不同隔离级别的关键。有很多方法可以实现它。根据对可能发生的冲突操作采取的不同策略,可以分为乐观并发控制和悲观并发控制两类。乐观并发控制:对于可能与并发执行冲突的操作,假设不会有真正的冲突,允许并发执行,解决冲突,直到真正发生冲突,比如允许事务回滚。悲观并发控制:对于并发执行过程中可能发生冲突的操作,假设一定会发生冲突,通过让事务等待(锁定)或中止(时间戳排序)的方式,将并行操作串行执行。实现方式有很多种:基于封锁的并发控制、基于时间戳的并发控制、基于有效性检查的并发控制、基于快照隔离的并发控制。数据库日志数据库运行过程中可能会出现故障。这些故障包括事务故障和系统故障两大类事务故障:如非法输入、系统死锁,导致交易无法继续进行。系统故障:例如由于软件错误或硬件错误导致的系统崩溃或暂停。这些故障可能会对事务和数据库的状态造成损害,因此必须提供一种技术来从各种故障中恢复,以保证数据库的一致性、事务的原子性和持久性。数据库通常以日志的形式记录数据库的操作,以便在发生故障时进行恢复,因此可称为日志恢复技术。数据库日志包括撤销和重做日志。分布式事务场景当我们的单库性能出现瓶颈时,我们可能会对数据库进行分区。这里所说的分区是指物理分区。分区后,不同的库可能位于不同的服务器上。这时候,单一数据库的ACID已经不能适应这种情况,而在这种ACID集群环境下,几乎很难保证集群的ACID,或者即使可以实现,效率和性能会大大减少。最关键的是很难扩展新的分区。这时候如果追求集群的ACID,我们的系统就会变差。这时候就需要引入一个新的理论原理来适应这种集群情况,这就是CAP原理。或者叫CAP定理?CAP定理CAP定理是由加州大学伯克利分校的EricBrewer教授提出的。他指出WEB服务不能同时满足以下三个属性:一致性:(相当于所有节点访问同一个最新的数据副本)可用性(Availability):(每个请求都能得到无错误的响应——但数据获取的数据不保证是最新数据)分区容错(Partitiontolerance):(就实际效果而言,分区相当于通信的时限要求。如果系统不能在时限内实现数据一致性,则意味着apartitionhasoccurred,andthechoicemustbebetweenCandAforthecurrentoperation.)根据定理,分布式系统只能满足三项item中的两项,不可能三项都满足。理解CAP理论的最简单方法是想象分区两侧各有两个节点。允许至少一个节点更新状态会导致数据不一致,即丢失C属性。如果为了保证数据的一致性,将分区一侧的节点设置为不可用,那么A属性就丢失了。除非两个节点可以相互通信,否则C和A都可以得到保证,进而导致P属性的丢失。因此,在设计分布式架构时,必须做出取舍。目前一般通过分布式缓存中各节点的最终一致性来提高系统的性能,而集群的数据一致性是通过多节点间的数据异步复制技术来实现的。通常使用像memcached这样的NOSQL作为实现手段。虽然memcached也可以处于分布式集群环境,但是对于一条数据来说,它总是存放在某个memcached服务器上。如果发生网络故障或服务器死机,则存储在该服务器上的所有数据都将无法访问。由于数据保存在内存中,重启服务器会导致所有数据丢失。当然你也可以自己实现一个机制,在分布式memcached之间同步持久化数据,但是实现起来难度很大。分区容忍度(Partitiontolerance)大多数分布式系统都分布在多个子网络中。每个子网称为一个分区。分区容忍意味着间隔通信可能会失败。例如,如果一台服务器位于中国,另一台服务器位于美国,这是两个地区,它们之间可能无法通信。图中P1和P2是两台跨服务器。P1向P2发送一条消息,P2可能不会收到该消息。在设计系统时必须考虑到这种情况。一般来说分区容错是无法避免的,所以可以认为CAP的P总是成立的。CAP定理告诉我们剩下的C和A不能同时做。一致性(Consistency)一致性是指写操作之后的读操作必须有返回值。比如一条记录v1=1,用户对P1发起写操作,修改为v1=10,然后用户的读操作会得到v1=10,这就叫一致性。问题是用户可能发起了对P2的读操作,由于P2的值没有变化,返回的是v0。P1和P2读操作结果不一致,不满足一致性。为了让P2也变成v1=10,需要在P1写的时候让P1发消息给P2,要求P2也变成v1=10。可用性(Availability)可用性是指只要收到用户的请求,服务器就必须响应。用户可以选择对P1或P2发起读操作。不管是哪个服务器,只要收到请求,就必须告诉用户v1的值,否则可用性得不到满足。一致性和可用性的矛盾一致性和可用性,为什么不能同时成立呢?答案很简单,因为可能存在通信故障(即出现分区容错)。如果保证P2的一致性,那么P1必须在写操作的时候对P2的读写操作加锁。只有数据同步后,才能重新开启读写。在锁定期间,P2不能读也不能写,没有可用性。如果P2的可用性得到保证,那么P2一定不能被锁定,因此一致性不成立。综上所述,P2无法同时做到一致性和可用性。系统设计时只能选择一个目标。如果追求一致性,就不能保证所有节点的可用性;如果追求所有节点的可用性,就无法做到一致性。那么在什么情况下,可用性高于一致性呢?例如,当一个网页发布到CDN时,多个服务器都有该网页的副本。后来发现错误,需要更新网页。此时每台服务器只能更新一次。一般来说,网页的更新并不特别强调一致性。短时间内,有的用户会拿到旧版本,有的用户会拿到新版本,所以问题不会特别大。当然,大家最终还是会看到新版本的。因此,这种场合是可用性高于一致性。通用产品Ereka->ereka是SpringCloud系列的一个组件,用于服务注册和发现。作为服务发现的实现,它在设计时考虑了可用性并保证了AP??。Zookeeper->Zookeeper在实现上牺牲了可用性,保证一致性(单调一致性)和分区容错,即:CP。所以这也是SpringCloud放弃zookeeper而选择Ereka的原因。当Zookeeper的master挂掉后,会在30-120s之间进行leader选举。这个类似于redis的哨兵机制。Zookeeper在选举期间不可用。这么长时间不能注册服务都让人难以忍受,更别说30s了。5s是受不了的。这时候Zookeeper集群就会瘫痪。这也是Zookeeper的CP,维持节点的一致性,牺牲A/高可用。但是Eureka不会,即使Eureka的一部分挂了,还有其他节点可以使用。他们保持水平关系,但信息可能不一致。这就是AP,牺牲了C/一致性。BASE理论,上面说了,CAP定理是三个词的缩写,BASE也是一样,是BasicallyAvailable(基本可用)、Softstate(软状态)、Eventuallyconsistent这三个词的缩写(最终一致性)。为什么要使用BASE理论?CAP定理只能三选二。CAP理论表明,对于一个分布式系统来说,它不可能同时满足Consistency(强一致性)、Availability(可用性)和Partitiontolerance(分区容错)这三个需求。条件,最多满足其中两个。必须选择分区容错。对于互联网,由于网络环境是不可信任的,因此必须满足分区容错性(P)。对于用户体验,首先选择可用性。现在你只能在一致性和可用性之间做出选择。大多数情况下,大家会选择牺牲部分一致性来保证可用性,因为你不返回用户数据。这次体验太差了。我宁愿拒绝这项服务。可以访问但是没有数据。当然,在严格的场景下,比如支付场景,必须要满足强一致性,那就另当别论了。但是放弃了一致性的系统就失去了存在的意义。好吧,我们只能放弃一致性,但是我们真的做到了,放弃了一致性。你能相信现在这个系统返回的数据吗?没有一致性,系统中的数据就会从根本上变得不可信,那么这些数据有什么用,那么系统就没有价值了,根本就没有用。上面说了,由于我们谁都不能舍弃这三个,但是CAP定理限制我们不能同时满足这三个,在这种情况下,我们会选择尽可能接近CAP定理,即尝试满足C、A、P。这是大势所趋接下来,BASE定理出现了。当强一致性(Strongconsistency)的核心思想无法保证(分区容错性和可用性满足系统)时,我们可以根据业务本身的特点,采用合适的方法实现最终一致性(Eventualconsistency)。基本可用(BasicallyAvailable)是相对于正常系统而言,响应时间的损失常见于以下几种情况:正常情况下,搜索引擎在0.5秒内将结果返回给用户,基本可用的搜索结果可能需要更长的1秒、2秒甚至3秒。如下图,用户原本可以10ms从redis读取数据,但在某些情况下,为了保证一致性,从MySql读取数据需要1s,用户以更长的时间为代价获取到数据。功能缺失:在电商网站上,正常情况下,用户可以顺利完成每笔订单,但到了促销的时候,为了应对并发,保障购物的稳定性,可能会引导部分用户降级系统。页。软态软态相对于原子性是原子的(硬态)->要求多个节点的数据副本一致,是一种“硬态”。硬态我们之前学过,指的是ACID的原子性。如下图,硬状态只有订单状态、积分发送成功、仓单下单成功,即三者同时成功,才算支付成功。软状态(弱状态)->允许系统中的数据以一种中间状态存在,并认为这种状态不影响系统的整体可用性,即允许系统在数据副本中有数据延迟多个不同的节点。软状态不需要完全遵守ACID的原子性。首先将订单状态修改为支付成功,然后告诉用户支付成功。剩下的就是异步发送mq消息通知信用服务和仓库服务。即使消费失败,也会重启MQ消息。发送(重试)。最终一致(Eventuallyconsistent)弱一致性与强一致性相反。系统不保证连续进程或线程的访问会返回最新的更新值。数据写入成功后,系统不承诺立即读取最新写入的值,也不承诺需要多长时间读取。但是它会尽量保证数据在一定的时间级别(比如秒级)之后能够达到一致的状态。最终一致性是弱一致性的一种特殊形式。强一致性和弱一致性:其实数据一致性只有两种,强一致性和弱一致性。强一致性也称为线性一致性,其他所有一致性都是弱一致性的特例。所谓强一致性就是复制是同步的,弱一致性就是复制是异步的。
用户更新网站头像。在某个时间点,用户向主库发送更新请求,主库稍后收到请求。在某个时候,主库会将数据变化转发给自己的从库。最后主库通知用户更新成功。
如果主库需要等待从库确认,确保从库收到写操作,然后返回“更新成功”,让新头像对其他用户可见,那么复制是同步的,即强一致性。如果主库写入成功后不等待从库响应,而是直接返回“更新成功”,则复制是异步的,即弱一致性。
强一致性可以保证从库与主库的数据一致。如果主库突然宕机,我们仍然可以保证数据的完整性。但是如果从库宕机或者网络不通,主库就无法完成写操作。
实际中,我们通常是让一个从库同步,其他的从库异步。如果这个同步从站有问题,另一个异步从站被同步。这确保始终有两个节点具有完整的数据:master和syncslave。这种配置称为半同步。X/OpenDTP模型和XA规范X/Open,即目前的开放组织,是一个独立的组织,主要负责制定各种行业技术标准。官网地址:http://www.opengroup.org/。X/Open组织主要由知名公司或制造商支持。这些组织不仅遵循X/Open组织定义的行业技术标准,而且还参与标准的制定。下图为目前开放组的主要成员(官网截图):DTP参考模型:分布式事务处理:参考模型DTPXA规范:分布式事务处理:XA规范参考文档维基百科-数据库事务维基百科-CAP定理数据库事务详解概念及其实现原理分布式BASE定理面试必问:分布式事务六解漫画:什么是分布式事务?说说分布式事务,说说分布式事务的解决方案?不,最终一致性CAP定理的含义分布式事务概述我是鱼虎神,欢迎大家关注我的微信公众号:wzm2zsd