在分布式系统的数据一致性问题(一)里面,简单的介绍了分布式数据的同步问题,上面的问题比较抽象,在目前的互联网应用中还很少见,这次在通过一个比较常见的例子,让大家更深入的了解一下分布式系统设计中关于数据一致性的问题
这次我们拿我们经常使用的功能来考虑吧,最近网购比较热门,就以京东为例的,我们来看看京东的一个简单的购物流程
用户在京东上下了一个订单,发现自己在京东的账户里面有余额,然后使用余额支付,支付成功之后,订单状态修改为支付成功,然后通知仓库发货。假设订单系统,支付系统,仓库系统是三个独立的应用,是独立部署的,系统之间通过远程服务调用。
订单的有三个状态:I:初始 P:已支付 W:已出库,订单金额100, 会员帐户余额200
如果整个流程比较顺利,正常情况下,订单的状态会变为I->P->W,会员帐户余额100,订单出库。
但是如果流程不顺利了?考虑以下几种情况
1:订单系统调用支付系统支付订单,支付成功,但是返回给订单系统数据超时,订单还是I(初始状态),但是此时会员帐户余额100,会员肯定会马上找京东骂京东,为啥不给老子发货,我都付钱了
2:订单系统调用支付系统成功,状态也已经更新成功,但是通知仓库发货失败,这个时候订单是P(已支付)状态,此时会员帐户余额是100,但是仓库不会发货。会员也要骂京东。
3:订单系统调用支付系统成功,状态也已经更新成功,然后通知仓库发货,仓库告诉订单系统,没有货了。这个时候数据状态和第二种情况一样。
对于问题一,我们来分析一下解决方案,能想到的解决方案如下
1 假设调用支付系统支付订单的时候先不扣钱,订单状态更新完成之后,在通知支付系统你扣钱
如果采用这种设计方案,那么在同一时刻,这个用户,又支付了另外一笔订单,订单价格200,顺利完成了整个订单支付流程,由于当前订单的状态已经变成了支付成功,但是实际用户已经没有钱支付了,这笔订单的状态就不一致了。即使用户在同一个时刻没有进行另外的订单支付行为,通知支付系统扣钱这个动作也有可能完不成,因为也有可能失败,反而增加了系统的复杂性。
2 订单系统自动发起重试,多重试几次,例如三次,直到扣款成功为止。
这个看起来也是不错的考虑,但是和解决方案一样,解决不了问题,还会带来新的问题,假设订单系统第一次调用支付系统成功,但是没有办法收到应答,订单系统又发起调用,完了,重复支付,一次订单支付了200。
假设支付系统正在发布,你重试多少次都一样,都会失败。这个时候用户在等待,你怎么处理?
3 在第二种方案的基础上,我们先解决订单的重复支付行为,我们需要在支付系统上对订单号进行控制,一笔订单如果已经支付成功,不能在进行支付。返回重复支付标识。那么订单系统根据返回的标识,更新订单状态。
接下来解决重试问题,我们假设应用上重试三次,如果三次都失败,先返回给用户提示支付结果未知。假设这个时候用户重新发起支付,订单系统调用支付系统,发现订单已经支付,那么继续下面的流程。如果会员没有发起支付,系统定时(一分钟一次)去核对订单状态,如果发现已经被支付,则继续后续的流程。
这种方案,用户体验非常差,告诉用户支付结果未知,用户一定会骂你,你丫咋回事情,我明明支付了,你告诉我未知。假设告诉用户支付失败,万一实际是成功的咋办。你告诉用户支付成功,万一支付失败咋办。
4 第三种方案能够解决订单和支付数据的一致性问题,但是用户体验非常差。当然这种情况比较可能是少数,可以牺牲这一部分的用户体验,我们还有没有更好的解决方案,既能照顾用户体验,又能够保证资金的安全性。
我们再回来看看第一种方案,我们先不扣钱,但是有木有办法让这一部分钱不让用户使用,对了,我们先把这一部分钱冻结起来,订单系统先调用支付系统成功的时候,支付系统先不扣钱,而是先把钱冻结起来,不让用户给其他订单支付,然后等订单系统把订单状态更新为支付成功的时候,再通知支付系统,你扣钱吧,这个时候支付系统扣钱,完成后续的操作。
看起来这个方案不错,我们仔细在分析一下流程,这个方案还存在什么问题,假设订单系统在调用支付系统冻结的时候,支付系统冻结成功,但是订单系统超时,这个时候返回给用户,告知用户支付失败,如果用户再次支付这笔订单,那么由于支付系统进行控制,告诉订单系统冻结成功,订单系统更新状态,然后通知支付系统,扣钱吧。如果这个时候通知失败,木有问题,反正钱都已经是冻结的了,用户不能用,我只要定时扫描订单和支付状态,进行扣钱而已。
那么如果变态的用户重新拍下来一笔订单,100块钱,对新的订单进行支付,这个时候由于先前那一笔订单的钱被冻结了,这个时候用户余额剩余100,冻结100,发现可用的余额足够,那就直接在对用户扣钱。这个时候余额剩余0,冻结100。先前那一笔怎么办,一个办法就是定时扫描,发现订单状态是初始的话,就对用户的支付余额进行解冻处理。这个时候用户的余额变成100,订单数据和支付数据又一致了。假设原先用户余额只有100,被冻结了,用户重新下单,支付的时候就失败了啊,的确会发生这一种情况,所以要尽可能的保证在第一次订单结果不明确的情况,尽早解冻用户余额,比如10秒之内。但是不管如何快速,总有数据不一致的时刻,这个是没有办法避免的。
第二种情况和第三种情况如何处理,下次在分析吧。
由于互联网目前越来越强调分布式架构,如果是交易类系统,面临的将会是分布式事务上的挑战。当然目前有很多开源的分布式事务产品,例如java JPA,但是这种解决方案的成本是非常高的,而且实现起来非常复杂,效率也比较低下。对于极端的情况:例如发布,故障的时候都是没有办法保证强一致性的。
相关推荐
分布式系统数据一致性介绍.docx
为了便于讨论问题,先简单介绍下数据一致性的基础理论。当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。根据...
介绍分布式理论的文档:Paxos/Raft 分布式一致性算法原理 剖析及其在实战中的应用
大数据背景下分布式系统的数据一致性策略
在大数据场景下,分布式数据库的数据一致性管理是其最重要的内核技术之一,也是保证分布式数据库满足数据库最基本的ACID特性中的“一致性”(Consistency)的保障,在分布式技术发展下,数据一致性的解决方法和技术也...
#资源达人分享计划#
分布式系统:数据一致性解决方案.docx
介绍了分布式系统的定义、实现原则和几种形式,详细介绍了微服务架构的分布式系统,并使用Spring Cloud框架演示了一个完整的微服务系统的实现过程。 5-1 CAP原则和BASE理论简介 5-2 分布式系统综述 5-3 SpringCloud...
分布式系统中的复制和一致性(续)复制事务服务`每个副本管理器以与非复制数据相同的方式提供对其自身数据项的并发控制和恢复a各种客户端对复制数据项执行的事务的影响与执行它们时的效果相同在一个数据项上一次一个...
在分布式系统中,同时满足“一致性”、“可用性”和“分区容错性”三者是不可能的。分布式系统的事务一致性是一个技术难题,各种解决方案孰优孰劣? 在OLTP系统领域,我们在很多业务场景下都会面临事务一致性方面的...
从Paxos到ZooKeeper一书高清的PDF、带完整书签,质量很好!
#资源达人分享计划#
分布式系统的数据分布、复制、一致性、容错、可扩展性等。范型篇--介绍谷歌、微软、阿里巴巴等知名互联网公司的大规模分布式存储系统架构,涉及分布式文件系统、分布式键值系统、分布式表格系统以及分布式数据库技术...
#资源达人分享计划#
数据复制,就是将数据库中的数据拷贝到另外一个或多个不同的物理站点上,从而保持源数据库与目标数据库中指定数据的一致性。数据复制通过在多个站点上建立备份,能够提高数据的安全性,同时也提高了数据的可用性,这...
#资源达人分享计划#
现在的问题是,假设成都上海各自的数据中心有记录变更,需要先同步到主数据中心,主数据中心更新完成之后,在把最新的数据分发到上海,成都的地方数据中心A,地方数据中心更新数据,保持和主数据中心一致性(数据库...
如何保证海量数据的一致性?如何保证海量数据的高可靠性?如何保证数据高安全性?如何保证分布式存储系统的高扩展性?如何保证分布式存储系统的负载均衡?!如何保证分布式存储系统的高稳定性?! 本次课程,将会...