分布式系统中,为保证数据的高可用,通常将数据保留多个副本,这些副本放置在不同的物理机上。
在数据有多副本的情况下,如果网络,服务器,软件本身故障,会导致部分副本写入成功,部分副本写入失败。造成各个副本之间数据不一致,数据内容冲突。
CAP理论认为:分布式环境下设计和部署系统保持3个核心需求:
一致性,可用性,可伸缩性
一致性:
这个和数据库ACID的一致性类似,但这里关注的所有数据节点的数据一致性和正确性,而数据库ACID关注的在一个事务内,对数据的约束。分布式环境中,更新操作执行后所有用户都应该读取到新值。
可用性:
每一个操作总是能够在一定时间内返回结果,系统必须就请求返回,必须有响应结果,成功或失败。
可伸缩性:
是否对数据进行区分,考虑到性能和业务伸缩性。
一些分布式系统通过复制数据提高系统可靠性和容错性,并且将数据的不同副本存放在不同机器。
强一致性:
当更新操作完成之后,任何多个后续进程或现场的访问都会返回最新结果。这种实时性会牺牲可用性。
弱一致性:
系统并不保证后续进程或现场的访问会返回最新更新结果。用户读到的数据可能不是最新,这段时间称为:不一致窗口。系统在数据写入成功之后,不承诺可读到最新值,不承诺多久可以读到。
最终一致性:
弱一致性的一种特例。系统保证在没有后续更新前提下,系统最终返回上一次更新结果值,在没有故障发生前提下,不一致窗口时间内,受通信延迟,系统负载和副本数量影响。DNS是一个最典型最终一致性系统。
跨行转账问题是一个典型的分布式事务,用户A向B的一个转账1000,要进行A的余额-1000,B的余额+1000,显然必须保证这两个操作的事务性。 类似的还有,电商系统中,当有用户下单后,除了在订单表插入记,还要在商品表更新库存等,特别是随着微服务架构的流行,分布式事务的场景更变得更普遍。
两阶段提交协议是协调所有分布式原子事务参与者,并决定提交或取消(回滚)的分布式算法。
在两阶段提交协议中,系统一般包含两类机器(或节点):
当协调者出错,同时参与者也出错时,两阶段无法保证事务执行的完整性。 考虑协调者再发出commit消息之后宕机,而唯一接收到这条消息的参与者同时也宕机了。 那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交。
三阶段提交协议在协调者和参与者中都引入超时机制,并且把两阶段提交协议的第一个阶段拆分成了两步:询问,然后再锁资源,最后真正提交。
3阶段CanCommit阶段和2阶段准备阶段很像。 协调者向参与者发送Commit请求,参与者如果可以提交就Yes响应,否则No响应。
根据第一阶段反应情况决定执行PreCommit操作。
如Yes:就进行事务的预执行:
发送预提交请求,进入Prepared阶段。 事务预提交,执行事务操作,将undo和redo信息记录到事务日志中。 响应反馈,如果事务成功执行,等待最终指令。
如果No,或等待超时:中断事务:
发送中断请求。 中断事务。
该阶段进行真正的事务提交,两种情况:
执行提交:
发送提交请求,将从鱼提交进入提交状态。 事务提交,上面执行成功执行正式的事务提交。在事务提交之后释放事务资源。 响应反馈,事务提交之后反馈。 完成事务。收到反馈之后,完成事务。
中断事务:
没有收到反馈,中断事务。
两阶段在准备阶段和提交阶段之间,插入预提交阶段,使三阶段变成CanCommit,PreCommit,DoCommit阶段。 PreCommit是一个缓存,保证在最后提交阶段之前各个节点状态一致的。