引言
分布式系统(distributed system)是建立在网络之上的软件系统。正是因为软件的特性,所以分布式系统具有高度的内聚性和透明性。因此,网络和分布式系统之间的区别更多的在于高层软件(特别是操作系统),而不是硬件。内聚性是指每一个数据库分布节点高度自治,有本地的数据库管理系统。透明性是指每一个数据库分布节点对用户的应用来说都是透明的,看不出是本地还是远程。在分布式数据库系统中,用户感觉不到数据是分布的,即用户不须知道关系是否分割、有无副本、数据存于哪个站点以及事务在哪个站点上执行等。
1、什么是分布式事务
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。以上是百度百科的解释,简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
2、分布式事务的产生的原因
数据库分库分表
当数据库单表一年产生的数据超过1000W,那么就要考虑分库分表,具体分库分表的原理在此不做解释,以后有空详细说,简单的说就是原来的一个数据库变成了多个数据库。这时候,如果一个操作既访问01库,又访问02库,而且要保证数据的一致性,那么就要用到分布式事务。
应用SOA化
所谓的SOA化,就是业务的服务化。比如原来单机支撑了整个电商网站,现在对整个网站进行拆解,分离出了订单中心、用户中心、库存中心。对于订单中心,有专门的数据库存储订单信息,用户中心也有专门的数据库存储用户信息,库存中心也会有专门的数据库存储库存信息。这时候如果要同时对订单和库存进行操作,那么就会涉及到订单数据库和库存数据库,为了保证数据一致性,就需要用到分布式事务。
以上两种情况表象不同,但是本质相同,都是因为要操作的数据库变多了!
3、事务的ACID特性
原子性(A)
所谓的原子性就是说,在整个事务中的所有操作,要么全部完成,要么全部不做,没有中间状态。对于事务在执行中发生错误,所有的操作都会被回滚,整个事务就像从没被执行过一样。
一致性(C)
事务的执行必须保证系统的一致性,就拿转账为例,A有500元,B有300元,如果在一个事务里A成功转给B50元,那么不管并发多少,不管发生什么,只要事务执行成功了,那么最后A账户一定是450元,B账户一定是350元。
隔离性(I)
所谓的隔离性就是说,事务与事务之间不会互相影响,一个事务的中间状态不会被其他事务感知。
3.4、持久性(D)
所谓的持久性,就是说一单事务完成了,那么事务对数据所做的变更就完全保存在了数据库中,即使发生停电,系统宕机也是如此。
4、分布式事务的应用场景
4.1、支付
最经典的场景就是支付了,一笔支付,是对买家账户进行扣款,同时对卖家账户进行加钱,这些操作必须在一个事务里执行,要么全部成功,要么全部失败。而对于买家账户属于买家中心,对应的是买家数据库,而卖家账户属于卖家中心,对应的是卖家数据库,对不同数据库的操作必然需要引入分布式事务。
在线下单
买家在电商平台下单,往往会涉及到两个动作,一个是扣库存,第二个是更新订单状态,库存和订单一般属于不同的数据库,需要使用分布式事务保证数据一致性。
5、罕见的分布式事务解决方案
基于XA协议的两阶段提交
XA是一个分布式事务协议,由Tuxedo提出。XA中大致分为两部分:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如Oracle、DB2这些商业数据库都实现了XA接口,而事务管理器作为全局的调度者,负责各个本地资源的提交和回滚。XA实现分布式事务的原理如下:
总的来说,XA协议比较简单,而且一旦商业数据库实现了XA协议,使用分布式事务的成本也比较低。但是,XA也有致命的缺点,那就是性能不理想,特别是在交易下单链路,往往并发量很高,XA无法满足高并发场景。XA目前在商业数据库支持的比较理想,在mysql数据库中支持的不太理想,mysql的XA实现,没有记录prepare阶段日志,主备切换回导致主库与备库数据不一致。许多nosql也没有支持XA,这让XA的应用场景变得非常狭隘。
分布式系统的特点
分布性
分布式系统中的多台计算机都会在空间上随意分布,同时,机器的分布情况也会随时变动。
对等性
分布式系统中的计算机没有主从之分,组成分布式系统的所有计算机节点都是对等的。副本是分布式系统最常见的概念之一,指的是分布式系统对数据和服务提供的一种冗余方式。
并发性
在一个计算机网络中,程序运行中的并发操作是常见的,可能会并发操作一些共享资源,如数据库或者分布式存储等,如何高效的协调分布式并发操作也是分布式系统架构与设计中最大挑战之一。
缺乏全局时钟
因为分布式系统是由一系列在空间上随意分布的多个进程组成的,具有明显的分布性,这些进程之间通过交换消息来通信。因为缺乏全局时钟,因此很难界定两个事件发生的先后顺序。所以在设计阶段考虑的异常情况,一定会在系统实际运行中发生,并且,在系统运行过程中还会遇到很多在设计时未能考虑到的异常故障,所以在系统设计中不要放过任何异常情况。
三、分布式系统中常见的问题
通信异常
分布式系统需要在各个节点之间进行通信,因此每次网络通信都会伴随着网络不可用的风险(光纤、路由、DNS等硬件设备的不可用)。
网络分区
由于网络发生异常情况,导致分布式系统中部分节点之间的网络延迟不断增大,最终导致组成分布式系统中只有部分节点能够进行正常通信,这种情况为网络分区,俗称“脑裂”。当出现网络分区时,分布式系统就会出现局部小集群,在极端情况下,这些小集群会独立完成原本需要整个分布式系统才能完成的功能,包括数据的事务处理,这就对分布式一致性提出非常大的挑战。
三态
因为网络的问题,所以分布式系统每次请求与响应存在特有的“三态”概念,即成功、失败和超时。由于网络部可靠性,虽然绝大部分情况下,网络通信能够接受到成功失败响应,但网络异常下,就会出现超时现象,通常有以下两种情况:
由于网络原因,请求并没有被成功的发送到接收方,而是在发送过程就发生了丢失现象。
该请求成功的被接收方处理后,但在响应反馈给发送方过程中,发生丢失现场。
分布式实战
实战的关注点是训练建模思路,所以这些例子都按照挑战、构思、架构三个步骤进行讲解。受限于保密性要求,有些细节并未给出,但这些细节并不影响讲解的完整性。
需要声明的是,这里的解决方案并不是所处场景的最优方案。但是,任何一个稍微复杂的问题,都没有最优解决方案,更谈不上唯一的解决方案。实际上,工程师每天所追寻的只是在满足一定约束条件下的可行方案。当然不同的约束会导致不同的方案,约束的松弛度决定了工程师的可选方案的宽广度。
信息采集处理
信息采集处理应用广泛,例如:广告计费、用户行为收集等。作者碰到的具体项目是为广告系统设计一套高可用的采集计费系统。
典型的广告CPC、CPM计费原理是:收集用户在客户端或者网页上的点击和浏览行为,按照点击和浏览进行计费。计费业务有如下典型特征:
采集者和处理者解耦,采集发生在客户端,而计费发生在服务端。
计费与钱息息相关。
重复计费意味着灾难。
计费是动态实时行为,需要接受预算约束,如果消耗超过预算,则广告投放需要停止。
用户的浏览和点击量非常大。
挑战
计费业务的典型特征给我们带来了如下挑战:
高吞吐量--广告的浏览和点击量非常巨大,我们需要设计一个高吞吐量的采集架构。
高可用性--计费信息的丢失意味着直接的金钱损失。任何处理服务器的崩溃不应该导致系统不可用。
高一致性要求--计费是一个实时动态处理过程,但要受到预算的约束。收集到的浏览和点击行为如果不能快速处理,可能会导致预算花超,或者点击率预估不准确。所以采集到的信息应该在最短的时间内传输到计费中心进行计费。
完整性约束--这包括反作弊规则,单个用户行为不能重复计费等。这要求计费是一个集中行为而非分布式行为。
持久化要求--计费信息需要持久化,避免因为机器崩溃而导致收集到的数据产生丢失。
构思
采集的高可用性意味着我们需要多台服务器同时采集,为了避免单IDC故障,采集服务器需要部署在多IDC里面。
实现一个高可用、高吞吐量、高一致性的信息传递系统显然是一个挑战,为了控制项目开发成本,采用开源的消息中间件进行消息传输就成了必然选择。
完整性约束要求集中进行计费,所以计费系统发生在核心IDC。
计费服务并不关心采集点在哪里,采集服务也并不关心谁进行计费。
根据以上构思,我们认为采集计费符合典型的“生产者消费者模型”。
架构
采集计费系统架构图如下:
用户点击浏览收集服务(Click/View Collector)作为生产者部署在多个机房里,以提高收集服务可用性。
每个机房里采集到的数据通过消息队列中间件发送到核心机房IDC_Master。
Billing服务作为消费者部署在核心机房集中计费。
采用此架构,我们可以在如下方面做进一步优化:
提高可扩展性,如果一个Billing部署实例在性能上无法满足要求,可以对采集的数据进行主题分区(Topic Partition)计费,即采用发布订阅模式以提高可扩展性(Scalability)。
全局排重和反作弊。采用集中计费架构解决了点击浏览排重的问题,另一方面,这也给反作弊提供了全局信息。
提高计费系统的可用性。采用下文单例服务优化策略,在保障计费系统集中性的同时,提高计费系统可用性。
总结
以 上就是我对Java开发大型互联网架构分布式事物介绍及分布式实战问题及其优化总结,分享给大家,觉得收获的话可以点个关注收藏转发一波喔,谢谢大佬们支持!
最后,每一位读到这里的网友,感谢你们能耐心地看完。希望在成为一名更优秀的Java程序员的道路上,我们可以一起学习、一起进步!都能赢取白富美,走向架构师的人生巅峰!