面试题答案
一键面试1. 两阶段提交(2PC)在JDBC场景中的应用
- 应用流程:
- 第一阶段(投票阶段):协调者向所有参与事务的数据库节点(参与者)发送准备(Prepare)消息。各参与者接收到消息后,执行SQL语句的预检查,例如检查数据的完整性、锁的获取等,但不真正提交事务。如果预检查成功,参与者向协调者回复“准备就绪(Ready)”;否则回复“失败(Abort)”。在JDBC中,这意味着通过
Connection.prepareStatement
等方法执行SQL语句,使用Connection.setAutoCommit(false)
开启事务,并进行必要的检查。 - 第二阶段(提交/回滚阶段):如果协调者收到所有参与者的“准备就绪”回复,那么向所有参与者发送提交(Commit)消息,参与者接收到提交消息后正式提交事务(在JDBC中通过
Connection.commit
方法)。如果有任何一个参与者回复“失败”,协调者向所有参与者发送回滚(Rollback)消息,参与者接收到回滚消息后回滚事务(在JDBC中通过Connection.rollback
方法)。
- 第一阶段(投票阶段):协调者向所有参与事务的数据库节点(参与者)发送准备(Prepare)消息。各参与者接收到消息后,执行SQL语句的预检查,例如检查数据的完整性、锁的获取等,但不真正提交事务。如果预检查成功,参与者向协调者回复“准备就绪(Ready)”;否则回复“失败(Abort)”。在JDBC中,这意味着通过
- 面临挑战及解决:
- 单点故障:协调者一旦崩溃,整个事务处理可能陷入不确定状态。解决方法可以采用选举机制,例如使用ZooKeeper,当协调者故障时,从参与者中选举出新的协调者,新协调者通过询问参与者的事务状态来决定是提交还是回滚事务。
- 阻塞问题:在第二阶段,参与者需要等待协调者的指令,期间资源被锁定,可能造成长时间阻塞。可以设置超时机制,当参与者等待超时后,可以主动询问协调者事务状态,避免无限期阻塞。
2. 三阶段提交(3PC)在JDBC场景中的应用
- 应用流程:
- 第一阶段(CanCommit阶段):协调者向参与者发送CanCommit消息,询问参与者是否可以执行事务。参与者接收到消息后,进行一些轻量级的检查,如检查自身是否处于正常运行状态等,然后回复协调者可以(Yes)或不可以(No)执行事务。在JDBC中,此阶段可以进行一些基本的数据库连接状态检查等操作。
- 第二阶段(PreCommit阶段):如果协调者收到所有参与者的“可以”回复,向参与者发送PreCommit消息。参与者接收到消息后,执行与2PC第一阶段类似的预检查和资源锁定操作,并回复协调者准备就绪(Ready)或失败(Abort)。JDBC操作与2PC第一阶段类似,通过
Connection.prepareStatement
执行SQL语句,开启事务并进行预检查。 - 第三阶段(DoCommit阶段):如果协调者收到所有参与者的“准备就绪”回复,向参与者发送DoCommit消息,参与者正式提交事务(
Connection.commit
)。如果有任何一个参与者回复“失败”,或者协调者等待超时,协调者向参与者发送Abort消息,参与者回滚事务(Connection.rollback
)。
- 面临挑战及解决:
- 复杂性增加:相比2PC,3PC增加了一个阶段,使得系统复杂度上升。需要仔细设计和测试各个阶段的逻辑,确保其正确性和稳定性。
- 网络分区:在网络分区情况下,可能导致部分参与者收到不同的指令。可以通过引入全局时钟或类似于Paxos算法的一致性协议来解决,确保不同分区内的节点对事务状态达成一致。
3. TCC(Try - Confirm - Cancel)模式在JDBC场景中的应用
- 应用流程:
- Try阶段:业务逻辑层调用各个服务的Try方法,在每个服务内部,通过JDBC执行SQL语句进行资源预留。例如,在涉及资金转账的分布式事务中,转出账户服务的Try方法可能通过JDBC执行SQL语句冻结转出金额,转入账户服务的Try方法可能通过JDBC执行SQL语句预留转入金额的空间。
- Confirm阶段:如果所有服务的Try方法都执行成功,业务逻辑层调用各个服务的Confirm方法,各个服务通过JDBC执行最终的提交操作,如将冻结的资金真正转出和转入。
- Cancel阶段:如果Try阶段有任何一个服务执行失败,业务逻辑层调用各个服务的Cancel方法,各个服务通过JDBC执行回滚操作,释放之前预留的资源,如解冻转出金额,取消转入金额的预留。
- 面临挑战及解决:
- 幂等性问题:Confirm和Cancel方法可能会被重复调用,需要保证这些方法的幂等性。可以通过在数据库中记录操作日志,每次执行方法前先检查日志,确保相同操作不会重复执行产生错误。
- 业务侵入性:TCC模式需要业务代码进行改造以实现Try、Confirm和Cancel方法,对业务的侵入性较大。需要在设计之初就充分考虑业务逻辑,合理划分服务和设计接口,尽量减少对原有业务的影响。