文档章节

TCC型分布式事务原理和实现之:原理介绍

黑客画家
 黑客画家
发布于 2017/05/15 10:50
字数 1567
阅读 6130
收藏 29

前言

      分布式事务的产生是由于需要同时对多个数据源进行事务操作(资源层),资源层的分布式事务常用的方案有JTA、spring事务等。随着微服务的盛行,服务层的分布式事务也日益重要,本文就着重讨论一种服务层分布式事务的实现原理:TCC。

钢性事务与柔性事务

      一般而言,满足ACID的事务的为钢性事务,满足BASE理论的为柔性事务。其中,柔性事务大致可以分为以下四种:

  • 两阶段型
  • 补偿型
  • 异步确保型
  • 最大努力通知型

TCC型事务

      TCC属于补偿型柔性事务,本质也是一个两阶段型事务,这与JTA是极为相似的,但是与JTA的不同点是,JTA属于资源层事务,而TCC是服务层事务。  

      在一个长事务( long-running )中 ,一个由两台服务器一起参与的事务,服务器A发起事务,服务器B参与事务,B的事务需要人工参与,所以处理时间可能很长。如果按照ACID的原则,要保持事务的隔离性、一致性,服务器A中发起的事务中使用到的事务资源将会被锁定,不允许其他应用访问到事务过程中的中间结果,直到整个事务被提交或者回滚。这就造成事务A中的资源被长时间锁定,系统的可用性将不可接受。
      WS-BusinessActivity提供了一种基于补偿的long-running的事务处理模型。还是上面的例子,服务器A的事务如果执行顺利,那么事务A就先行提交,如果事务B也执行顺利,则事务B也提交,整个事务就算完成。但是如果事务B执行失败,事务B本身回滚,这时事务A已经被提交,所以需要执行一个补偿操作,将已经提交的事务A执行的操作作反操作,恢复到未执行前事务A的状态。这样的SAGA事务模型,是牺牲了一定的隔离性和一致性的,但是提高了long-running事务的可用性。          

     在JTA事务中,所有需要被事务管理的资源(由不同厂商实现)都必须实现规定接口(比如XAResource中的commit和rollback等),同理,所有需要加入TCC事务的服务也必须提供相应的接口实现,在TCC中这些接口为:try、confirm、cancel(缩写为TCC)。TCC事务管理器会使用try、confirm、cancel接口协调多个服务进行事务处理,如下图所示:

                

           Try: 尝试执行业务
                 • 完成所有业务检查(一致性)
                 • 预留必须业务资源(准隔离性)          
            Confirm:确认执行业务
                 • 真正执行业务
                 • 不作任何业务检查
                 • 只使用Try阶段预留的业务资源 
                 • Confirm操作要满足幂等性
            Cancel: 取消执行业务
                 • 释放Try阶段预留的业务资源 
                 • Cancel操作要满足幂等性
            

            TCC与2PC协议比较:
                 • 位于业务服务层而非资源层
                 • 没有单独的准备(Prepare)阶段, Try操作兼备资源操作与准备能力 
                 • Try操作可以灵活选择业务资源的锁定粒度(以业务定粒度) 
                 • 较高开发成本
           

TCC方案设计

      一个好的TCC框架实现至少应该满足以下几个特点:

  • 不与特定的服务框架耦合:TCC作为服务层的分布式事务方案,自然离不开一些常用的微服务框架,比如:dubbo、dubbox、motan、hessian、grpc、thrift以及时下很火的spring cloud等。但是TCC框架本身不应该与特定服务框架绑定,无论服务框架是基于tcp还是http,无论是基于私有协议还是公有协议,TCC框架都应该能做到无缝整合。当然,框架本身可以针对特定的服务框架进行一些部分优化,比如针对dubbo,那么TCC框架本身可以充分利用dubbo隐式传参的特性进行事务上下文的传递,而不用显示的作为服务方法参数传递。
  • 提供基于注解的配置:提供基于注解而不是xml的服务配置方式,这样可以极大的方便服务的开发。注解用于标记try、confirm、cancel接口的具体实现,同时,被注解标记的TCC接口还会被框架提供的切面进行拦截,执行特定的事务逻辑。
    @Compensable(confirmMethod = "confirmRecord", cancelMethod = "cancelRecord",transactionContextEditor = DubboTransactionContextEditor.class)
    @Transactional
    public String record(CapitalTradeOrderDto tradeOrderDto) {
        return "success";
    }

    @Transactional
    public void confirmRecord(CapitalTradeOrderDto tradeOrderDto) {
     
    }

    @Transactional
    public void cancelRecord(CapitalTradeOrderDto tradeOrderDto) {
      
    }
  • 支持多种事务日志持久化机制:事务日志持久化的性能是影响TCC性能的一个很重要因素,因此支持多种持久化机制便于根据特定应用场景进行灵活选择,比如支持基于文件、基于redis(开启AOF)、基于zookeeper、基于mysql等等。使用何种持久化机制,框架应该支持在xml或者注解中进行配置。
  • 支持可配置recovery策略:对于异常的事务(比如Confirm失败),TCC框架应该提供recovery机制,它会对事务日志进行扫描监控,并根据策略进行recovery操作。策略必须是可以配置的(基于xml或者注解),配置项可以有:最大重试次数、recovery时间间隔、支持Cron表达式等。   
  • 使用spring:由于spring框架几乎存在于每一个java项目中,因此TCC框架有理由选择spring来进行:依赖注入、aop、spring声明式事务等。

系列文章

TCC型分布式事务原理和实现之:原理介绍

TCC型分布式事务原理和实现之:TransactionManager

TCC型分布式事务原理和实现之:Transaction与Participant

TCC型分布式事务原理和实现之:事务切面

TCC型分布式事务原理和实现之:事务recovery

TCC型分布式事务原理和实现之:兼容dubbo

 

© 著作权归作者所有

共有 人打赏支持
黑客画家
粉丝 119
博文 184
码字总数 460239
作品 0
杭州
高级程序员
加载中

评论(2)

黑客画家
黑客画家

引用来自“eonezhang”的评论

no update anymore?
双十一之前都会非常忙,估计更新都要等到双十一之后了,谢谢你对文章的关注:blush:
eonezhang
eonezhang
no update anymore?
shuaiqiyu/happylifeplat-tcc

happylifeplat-tcc 碧桂园旺生活平台解决分布式事务方案之tcc开源框架。基于java语言来开发(JDK1.8),支持dubbo,springcloud等rpc框架进行分布式事务。 因为文件名太长,大家在拉取代码的...

shuaiqiyu
2017/12/21
0
0
分布式事务:分布式事务原理概述

1、什么是分布式事务 分布式事务就是指事务的资源分别位于不同的分布式系统的不同节点之上的事务; 2、分布式事务产生的原因 2.1、数据库分库分表 在单库单表场景下,当业务数据量达到单库单...

绍辉
07/10
0
0
深入理解分布式事务(XA及rocketmq事务)

本文由码农网 – 吴极心原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! 我在上一期介绍了spring的事务原理(详情见《深入理解spring事务原理》),spring事务本质是单机下的...

tantexian
2016/11/23
195
0
GTS解密--GTS的原理、架构与特点

作者 赵成 日期 2018-01-01 标签 分布式事务 , GTS , Global Transaction Service, 柔性事务, TCC , XA两阶段提交协议 全局事务服务(Global Transaction Service,简称 GTS)是阿里新推出的...

chengxiaozc
01/05
0
0
深入理解分布式事务

Spring事务本质是单机下的事务,是由数据库本身保证的。今天,我将介绍一种比较复杂的事务:分布式事务。 1 什么是分布式事务 分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以...

小车车
2016/08/10
7
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

人生苦短:Python里的17个“超赞操作

人生苦短,我选Python”。那么,你真的掌握了Python吗? 1. 交换变量 有时候,当我们要交换两个变量的值时,一种常规的方法是创建一个临时变量,然后用它来进行交换。比如: # 输入 a = 5 b ...

糖宝lsh
53分钟前
4
0
咕泡-spring中常用设计模式概述

设计模式就是经验之谈,供后人借鉴,解决一些具有代表性的问题 设计模式来源于生活,反过来帮助我们更好生活 设计模式提升代码的可读性、可扩展性、维护成本、复杂业务问题 千万不要死记硬背...

职业搬砖20年
今天
2
0
day59-20180817-流利阅读笔记-待学习

假·照骗,真·社交焦虑 雪梨 2018-08-17 1.今日导读 发朋友圈之前,不少人为了展现更美好的生活状态会对照片加以“微调”,或是加个滤镜显得逼格更高,或是磨个皮瘦个脸拉个大长腿。现在,国...

aibinxiao
今天
23
0
OSChina 周五乱弹 —— 姑娘在这个节日里表白你接受么?

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @Sharon啊:完全被这个小姐姐圈粉了,学两首她的歌去哈哈 分享王贰浪的单曲《往后余生(翻自 马良)》 《往后余生(翻自 马良)》- 王贰浪 手...

小小编辑
今天
1K
17
为什么HashMap要自己实现writeObject和readObject方法?

为什么HashMap要自己实现writeObject和readObject方法? 如果你有仔细阅读过HashMap的源码,那么你一定注意过一个问题:HashMap中有两个私有方法。 private void writeObject(java.io.Objec...

DemonsI
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部