分布式环境下数据一致性的设计总结
相关理论:
在聊分布式环境下数据一致性问题之前我们先看一个理论(事务的ACID一定要知道的)CAP理论:
CAP理论由加州大学伯克利分校的计算机教授Eric Brewer在2000年提出,其核心思想是任何基于网络的数据共享系统最多只能满足数据一致性(Consistency)、可用性(Availability)和网络分区容忍(Partition Tolerance)三个特性中的两个,三个特性的定义如下:
C数据一致性:等同于所有节点拥有数据的最新版本
A可用性:数据具备高可用性
P分区容忍:容忍网络出现分区,分区之间网络不可达
在大规模的分布式环境下,网络分区是必须容忍的现实,于是只能在可用性和一致性两者间做出选择。 CAP理论带来的价值是指引我们在设计分布式系统时需要区分各种数据的特点,并仔细考虑在小概率的网络分区发生时究竟为该数据选择可用性还是一致性。
我们本次聊的是数据一致性,所以一切前提是CP。并且以资金账户解冻为例。
场景分类:
数据一致性场景大致可以分为弱一致性,强一致性。
所谓的弱一致性,就是有可能在某个时刻数据非一致,但是到达某个时间点以后总能保持一致,也即我们所说的最终一致性。 而强一致性就是需要保证数据的一致性是实时的,每一时刻都保持一致。
解决方案总结:
弱一致性的解决方案:
- 由外围系统重试,自身实现幂等,保证最终一致性。
比如用户解冻功能,后台web界面提供重试按钮,第一次操作可能解冻没有成功。用户可以不停的点击直到解冻成功,自身业务系统只要实现幂等即可。
该方案设计简单,业务系统不用太关心一致性的问题,只要自身系统实现业务幂等即可,无耦合性。
2. 依赖于事务型消息,通过消息重试,保证最终一致性。
上层业务无重试,无补偿,只能依赖于系统自身保证一致性。可以在完成合约解冻结之后,发送事务型消息,只要消息发送和合约解冻成功即可返回外围系统成功。后边账务的解冻依赖于消息中心的消息投递,如果失败,消息中心会由重试机制直到成功。如果业务推进不下去的化,需要人工接入。
该方案设计相对简单,只需要在原有流程中加入发送消息的逻辑,账务那边数据的保证交给消息中心去搞定。但是自身系统需接入消息中心,被调用方需要实现业务幂等,增加消息中心的耦合依赖。自身无法控制投递规则。
- 依赖于调度任务,通过调度任务重试,保证最终一致性。
上层业务无重试,无补偿,只能依赖于系统自身保证一致性。可以在完成合约解冻结之后,本地落地一张异步任务表。由定时任务定时扫描去调用账务进行解冻。
该方案对比依赖于消息中心的方案主要区别点在于失败后的数据落地在本系统内,不是消息中心,系统需增加一步任务表。自身能够完全掌握待恢复的数据,是否重试,是否终止都由自身系统决定,灵活性增加了。减少了消息中心的耦合,但是会增加调度中心的依赖。
强一致性的解决方案:
1. 引入协调者:
强一致性的解决依赖于中间协调者,中间协调者能够从全局把控该次业务涉及到的哪几系统。是否都成功了,是否存在部分失败,最终要提交还是要回滚。
已有的理论就是2PC两阶段提交理论。我自己理解的两阶段是这样的。
(发起方:发起分布式事务的系统。 参数者:被调用的系统)
第一阶段: 准备阶段。
发起方问参与者们你们可以提交吗? 参与者通常在本地事务试着提交一把,通常的做法就是设置中间表,将数据先写入中间表,如果写入成功,那么意味着我是可以提交了。
第二阶段:提交阶段。
发起方告诉协调者,好了参与者们都可以提交了,我先提交本地事务,你再去提交(或者回滚)他们的事务吧。
通过第一阶段的试提交,保证了整个分布式事务在第二阶段的成功率,使得如果出现不可提交的情况的时候能够及早发现及早回滚。可提交的情况下,能够保证正确提交。
该方案能够解决强一致性的需求,但是需要大量的接入成本。业务系统耦合两阶段框架,参与者系统需要保证幂等,增加中间表,并且实现二阶段提交回滚的方法供协调者调用。
总结:
业务上应该视业务需求考虑是需要强一致性还是弱一致性,然后再根据自身情况考虑选取哪种方案更加适合自己。以上分析都是基于自己的理解进行的总结,只是从宏观上进行了表达,里面还有很多细节需要探索。其中可能存在着某些错误,如果有请各位一定指出,互相学习。