性能优化实战(五):考拉下单分布式事务设计

96 阅读7分钟

如果你觉得这篇文章对你有帮助,请不要吝惜你的“关注”、“点赞”、“评价”、“收藏”,你的支持永远是我前进的动力~~~

本文是我在做网易考拉海购性能优化时的真实实践,希望对你也有帮助!!!


一、微服务化的困境

微服务是一种架构风格,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。微服务化具有以下优点:

  1. 灵活性:由于每个服务都可以独立部署和扩展,因此组织可以根据需求快速调整服务的规模和功能,提高了整个应用的灵活性和可维护性。
  2. 独立性:各个服务之间的解耦程度较高,单个服务的变更不会影响其他服务,降低了项目风险。
  3. 创新性:微服务鼓励小团队独立开发和迭代,有助于激发团队的创新能力,推动产品的持续改进。
  4. 可扩展性:服务可以根据负载情况进行水平扩展,轻松应对高流量和大数据场景。
  5. 容错性:服务之间的隔离性使得个别服务的故障不会导致整个应用的瘫痪,提高了系统的鲁棒性。

但同时,微服务化也存在一些挑战和缺点:

  1. 复杂性:随着服务数量的增加,管理和服务间的通信会变得更加复杂,需要更多的协调工作和监控机制。
  2. 数据一致性:在分布式系统中保持数据一致性的难度较大,特别是在处理事务时,需要特别关注数据的最终一致性问题。
  3. 运维成本:微服务架构下,需要进行更精细的服务治理、部署和监控,这增加了运维的复杂度和成本。
  4. 系统集成测试:由于服务众多,集成测试的难度和工作量都会大大增加,需要有效的自动化测试策略。
  5. 技术栈多样性:不同的服务可能会采用不同的技术和框架,这可能导致技术债务和维护困难。

其中最大的挑战我认为是数据的一致致问题。

要彻底服务化、系统要具备水平扩容、独立演进,DB也一定要随业务独立。那边就逃不开数据一致性问题,而通常需要分布式事务来解决。

二、标准TCC

TCC(Try-Confirm-Cancel)是一种分布式事务解决方案,它通过业务层面上的编程来保证事务的最终一致性。下面是TCC技术方案的详细解释:

基本概念

  • Try:尝试执行业务操作,完成所有业务检查,预留必须的业务资源。
  • Confirm:确认执行业务操作,真正执行业务,不做任何业务检查,只使用Try阶段预留的业务资源。
  • Cancel:取消执行业务操作,释放Try阶段预留的业务资源。

实现步骤

  1. Try阶段
    • 完成业务检查,确保业务可以正常执行。
    • 预留资源,例如冻结资金、锁定库存等。
    • 记录事务日志,用于后续的Confirm或Cancel操作。
  1. Confirm阶段
    • 在Try阶段成功的基础上,执行真正的业务操作。
    • 使用Try阶段预留的资源。
    • 通常情况下,Confirm阶段不会失败,因为所有业务检查和资源预留都在Try阶段完成了。
  1. Cancel阶段
    • 在Try阶段成功,但Confirm阶段失败或事务需要回滚时执行。
    • 释放Try阶段预留的资源。
    • 恢复业务数据到Try阶段之前的状态。

关键特性

  • 原子性:TCC通过Try、Confirm、Cancel三个操作的原子性来保证整个事务的原子性。
  • 一致性:通过Confirm和Cancel的最终执行来保证事务的一致性。
  • 隔离性:通过资源预留和释放来避免脏读、脏写等问题。
  • 持久性:事务日志的持久化确保了事务的持久性。

实现难点

  • 幂等性:Confirm和Cancel操作需要设计成幂等的,以避免重复执行导致的数据不一致。
  • 资源预留:如何合理预留资源,以及如何处理资源预留失败的情况。
  • 异常处理:如何处理网络异常、系统故障等情况,确保事务能够正确回滚。

适用场景

  • 需要强一致性的分布式系统。
  • 业务操作可以拆分为Try、Confirm、Cancel三个阶段。
  • 系统可以承受资源预留带来的短暂不一致。

三、考拉改进版TCC

我们的目标是构建简单、可靠、高性能的系统

真正重要的是满足业务需求,而不是追求抽象、绝对的系统特性。

我们对分布式事务的需求分析:

  1. 不强调复用 — 仅下单有强需求
  2. 下单扣减资源,不会造成资损 – 宁可长款,不可短款
  3. 事务消息、补偿机制可以解决其他场景
  4. 不考虑隔离性、嵌套事务等复杂特性
  5. 成功占绝对数量

因此我们参考标准TCC,结合考拉当时的实际情况,设计了考拉版本的TCC,我们称之为一阶段分布式事务。

考拉下单分布式事务中的TCC(Try-Confirm-Cancel):

  1. 业务发起方:负责协调整个分布式事务流程的角色,通常称为“事务协调者”。
  2. 开启事务:这是第一步操作,由业务发起方开始一个新的事务。
  3. confirm方法cancel方法
    • confirm方法:用于确认操作成功的方法。在所有参与方的操作都成功完成后,调用此方法来提交事务。
    • cancel方法:用于回滚操作失败的方法。如果在任何一步操作中出现错误或异常情况,则调用此方法来取消之前进行的所有操作。
  1. 业务参与方A和B:这两个是具体的业务服务节点,它们各自有自己的数据库。

和标准TCC的区别在于,去除了try预留资源的操作,直接扣减资源。因为有扣减之前的资源检查,这一步在绝大多数情况下都是可以成功的,一步就可以完成,这也是我们称之为“一阶段分布式事务”的原因了。

三、考拉版TCC实践

下面是考拉真实的下单分布式事务场景,可以很直观的看出我们的设计流程。这里不作过多解释。

我们的方案具有如下性能优点:

  1. DB开销非常低
  2. Dubbo异步开发,减少了耗时和线程开销
  3. 正向一阶段提交,避免不必要的RPC调用

我们也有阿里集团的公开数据做了对比:

  • 集团平均下单RT 462ms
  • 考拉平均下单RT 270ms,比集团平均水平要快。

在实现的过程中要注意如下三点:

  • 避免xa和减少锁时间:XA是一种分布式事务协议,而减少锁时间意味着减少了事务锁定的时间,这样可以提升系统的并发能力。
  • 支持两次空回滚:不能认为当时没有业务数据就无需再次执行回滚操作,要隔一段时间再次执行回滚操作,避免数据落库延迟导致的问题
  • 避免回滚风暴