两阶段提交协议(2PC)
转账功能开发
一、需求背景:
某T日,田小胖想往家乡的父母寄毕业后的第一笔工资,然后他兴高采烈来到楼下ATM机,拿出了自己的工资卡,开始输金额,输密码......
二、交易链路 A->B->C
假设某转账接口包含三个部分,银行内转账接口包含三个步骤:第一步校验,第二步扣款,第三步转账。
- A 服务器专门完成第一步,客户身份验证、银行卡密码校验、登记转账记录等功能。
- B 服务器专门完成第二步,负责把田小胖工资卡的钱暂时转到内部用于转账的账户。
C 服务器专门完成第三步,把钱转账到田小胖父母的储蓄卡账户。
田小胖操作ATM机,通过网络发送到某业务系统,业务系统接口调起A、B、C接口。
请问,假设你是开发这个接口的负责人,B机器扣完款了,C机器因为日志磁盘满导致JVM宕机,
你应该怎么做?
1、跑路
2、修生产数据把钱字段改过来,然后再把自己的银行卡账户加两个0
3、跑去问架构师拿分布式事务解决方案三、两阶段提交协议
2PC,是计算机网络尤其是在数据库领域内,为了使基于分布式系统架构下的所有节点在进行事务处理过程中能够保持原子性和一致性而设计的一种算法。
通常,二阶段提交协议也被认为是一种一致性协议,用来保证分布式系统数据的一致性。
说人话,在实践层面,协议=算法=一堆程序,TCP协议通过三次握手四次挥手保证可靠连接。
分布式系统通过2PC实现数据在不同节点的一致性。假设你6位密码保护的银行卡内有着10.00块钱,10.00块钱存在mysql的金额表的money字段。mysql有10机器副本。然后2PC就解决你的10.00块钱在这10台机器同步的问题。阶段一:提交事务请求
协调者组织各参与者对一次事务操作的投票表态过程,因此PC的阶段一也被称为“投票阶段”
- 事务询问:协调者向所有参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者的相应
- 执行事务:各参与者节点执行事务操作,并将Undo和Redo信息记入事务日志
- 各参与者向协调者反馈事务询问的响应:
如果参与者成功执行了事务操作,那么就反馈给协调者YES响应,表示事务可以执行;
如果参与者没有成功执行事务,那么就反馈给协调者NO响应,表示事务不可以执行。
阶段二:执行事务提交
协调者会根据各参与者的反馈情况来决定最终是否可以进行事务提交操作。
正常情况下包含执行事务提交和事务中断两种情况。
执行事务提交
- 发送提交请求:协调者向所有参与者节点发出Commit请求
- 事务提交:参与者接收到Commit请求后,会正式执行事务提交操作,并在完成提交之后释放在整个事务执行期间占用的事务资源。
- 反馈事务提交结果:参与者在完成事务提交之后,向协调者发送ACK消息。
4、完成事务:协调者接受到所有参与者反馈的Ack消息后,完成事务。
中断事务
假如任何一个参与者向协调者反馈了No响应,或者等待超时之后,协调者无法接收到所有参与者的反馈响应,那么就会中断事务。中断事务可以理解为分布式事务执行的异常情况处理,Client端执行是Rollback。
- 发送回滚请求:协调者向所有参与者节点发出Rollback请求。
- 事务回滚:参与者接收到Rollback请求后,会利用其在阶段一中的Undo来执行事务回滚操作,并在完成回滚之后释放在整个事务执行期间占用的资源
- 反馈事务回滚结果
参与者在完成事务回滚之后,向协调者发送ack消息 - 中断事务:协调者接收到所有参与者反馈的Ack消息后,完成事务中断。
四、2PC的示意图
事务提交
事务中断
2PC优缺点
- 优点:简单方便,能够保证分布式数据一致性
- 缺点:
1、同步阻塞:A、B、C三个接口是顺序调用
(Java API回环栅栏、CompleteFuture能够优化这一问题)
2、单点问题:协调者故障
3、脑裂:提交二阶段的过程会存在部分节点commit的情况,协调者故障,无法回滚
4、容错,任一节点失败都会导致整个事务失败
参考文献:
《从Paxos到Zookeeper 分布式一致性原理与实践.pdf》
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。