|   登录   |   注册   |   设为首页   |   加入收藏   

用户登录

close

用户名:

密码:

新用户注册

close

用户名:

密码:

密码确认:

电子邮箱:

关注内容:

个人主页:

帮助

close

龙宇网成立于2008年3月,网站进入整体运作于2010年10月1日。

在这里,我们把它做成了一个真正意义上的网站,完全以个人的信息为内容,以网友的需要为主导,全力搜罗各种信息,建立完善的网站功能,使网友在这里可以第一时间找到所需要的信息。

现在,经过三年的努力,网站的资料已经相当丰富,而网站得到了大家的喜爱和认可。

但,我们还是会继续努力下去,让网间的这份快乐继续持续下去,让这份闲暇时的日子,与快乐一并同行。

寻觅快乐,网住快乐,关注网络,是龙宇网的宣言与承诺。

分布式事务

分类: 流式计算 发布时间: 2018-02-08 14:53:54 浏览次数: 463
内容提要: 在实际业务应用场景中,我们不可避免的要采用分布式事务,但是分布式事务没有一个完全的解决方案,在设计过程中我们需要根据业务的实际情况进行取舍,或者失去一致性,或者失去效率、性能等。

在实际业务应用场景中,我们不可避免的要采用分布式事务,但是分布式事务没有一个完全的解决方案,在设计过程中我们需要根据业务的实际情况进行取舍,或者失去一致性,或者失去效率、性能等。

在说分布式事务之前,先温习几个概念,ACID和CAP。

ACID:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

ACID是关系型数据库的几个基本特性,需要满足这些特性,我们才可以称之为一个关系型数据库,而作为一个存储系统这些特性充分保证了我们数据的安全性和完整性。

CAP:一致性(Consistency)、可用性(Availablility)、分区容忍性(Partition Tolerance)。

CAP理论说的是任何分布式系统只能满足其中的亮点,没法三点同时满足。

一个简单例子来说一下分布式事务,假如我们要往MySQL和Redis同时写入数据,但是需求是若任何一个写入失败,就认为失败,数据就要回滚。MySQL和Redis是两套完全不同的存储集群。这个时候我们就要用到分布式事务。接下来我们说说分布式事务的复杂度,复杂关键是处理异常复杂,其他我们设计系统更多的是在考虑异常,而不是正常情况,作为一个架构师只看到正常情况,而看不到异常情况,那这个系统就要悲催了, 记住一句话:任何线上问题,都是异常或者多个异常凑到一起产生的。所以,不要抱有侥幸心理。

在实现分布式事务的时候,我们需要考虑两点:

1、数据回滚、提交策略

2、数据隔离机制

上述两点是紧密联系在一起的,我们将数据写入MySQL,但是还没有写入到Redis的时候,反之亦然, 我们在MySQL的数据就要设置为不可见,也就是用户不可以访问到 , 因为我们没法预测到之后的写Redis操作一定会成功。而且我们知道Redis只是一个KV的存储系统,是不支持数据隔离的,如果我们想在Redis上实现分布式事务的话,那需要Redis支持数据隔离,如果做不到,那就放弃在Redis上实现分布式事务。除非,你的系统不关心用户访问到脏数据。

数据回滚、提交策略,我们不得不的他的唯一方案,两阶段(2PC)提交。在事务的解决方案中两阶段提交是唯一的方案,任何其他方案都是对两阶段的优化和改进,三阶段(3PC)就是对二阶段的改进,本质还是二阶段,只是更细化而已。同理,在分布式系统的解决方案中,paxos是唯一的方案, 其他都是paxos的变种, Google Chubby 的作者Mike Burrows说过:“there is only one consensus protocol, and that's Paxos,- all other aporoaches are just broken version of Paxos”这个世界上只有分布式算法, 那就是paxos,其他都是残次品。虽然说的很夸张,但是事实就是这样。其他我们设计系统,我们的解决方式那么几个或者只有唯一的一个,万变不离其宗, 编程没有那么多复杂。下面结合MySQL两阶段提交的实现,来说说是不是的提交,这里不是分布式事务, 我们要先做到事务,在可以谈分布式事务。

MySQL两阶段提交:

1、prepare阶段, 数据写入InnoDB,当然MySQL的prepare阶段有很复杂的逻辑, 这里只列关键点。但是在这个时候,用户来访问时拿不到最新写入的数据。

2、commit阶段, 数据将写入磁盘,满足持久性。然后将InnoDB的数据生效。

在上述两个阶段中, 数据刷入磁盘是个关键点,MySQL认为数据进入到磁盘才认为写入成功,在刷磁盘之后执行的动作,如果有失败的情况,那数据就会重新执行一遍。但是如果数据在之前失败, 那么数据就会回滚。

通过上述的理解,我们发现在MySQL和Redis这两种存储系统中做事务,简直是不可能的事情,Redis都不满足ACID。 所以,我们在碰到这样的情况的时候,我们可以通过其他方式绕过去。尽量不要让自己的系统处理分布式事务。 变通方案:

数据在写入MySQL和Redis之前,先写入消息系统,只要数据写入消息系统成功,我们就认为数据写入成功,后面的在有数据同步服务将数据写入MySQL和Redis。这样的方案,也不是特别完美,因为同步服务也不能保证MySQL和Redis的数据完全一致,我们只能做到最终一致性,尽量缩短不一致的时间。

说来说去,分布式事务没有特别好的方案, 没有100%的方案,写代码在不完善,测试case也不全,这样的系统上线后,不出问题才怪。

15
20

分类: 流式计算   |   评论: 0   |   引用: 0   |   浏览次数: 463