概述
Hmily 是一款高性能分布式事务 tcc 开源框架。基于java语言来开发(JDK1.8),支持 Dubbo、Spring Cloud、Motan 等 RPC 框架进行分布式事务。
功能
- 高可靠性 :支持分布式场景下,事务异常回滚,超时异常恢复,防止事务悬挂
- 易用性 :提供零侵入性式的
Spring-Boot
,Spring-Namespace
快速与业务系统集成 - 高性能 :去中心化设计,与业务系统完全融合,天然支持集群部署
- 可观测性 :Metrics多项指标性能监控,以及admin管理后台UI展示
- 多种RPC : 支持
Dubbo
,SpringCloud
,Motan
,Sofa-rpc
,brpc
,tars
等知名RPC框架 - 日志存储 : 支持
mysql
,oracle
,mongodb
,redis
,zookeeper
等方式 - 复杂场景 : 支持RPC嵌套调用事务
必要前提
- 必须使用
JDK8+
- TCC模式必须要使用一款
RPC
框架, 比如 :Dubbo
,SpringCloud
,Montan
TCC模式
TCC是一种比较成熟的分布式事务解决方案,可用于解决跨库操作的数据一致性问题; TCC是服务化的两阶段编程模型,其Try,Confirm,Cancel3个方法均由业务编码实现。
- Try阶段: 完成所有业务检查(一致性),预留业务资源
- Confirm阶段: 确认执行业务操作,不做任何业务检查,只使用Try阶段预留的业务资源。
- Cancel阶段: 取消Try阶段预留的业务资源。
业务实现TCC 服务之后,该TCC服务将作为分布式事务的其中一个资源,参与到整个分布 式事务中;事务管理器分2个阶段协调服务,在第一个阶段调用所有TCC服务的Try方法, 在第二阶段执行所有TCC服务的Confirm或者Cancel方法。如果Try执行成功,则执行Confirm 进行确认业务操作;如果Try执行失败,则执行Cancel取消Try阶段预留的业务资源。
TCC常用的三种异常
- 第一种:空回滚 在没有调用Try方法的情况下,调用了第二阶段的Cancel方法,这时就需要空回滚。
- 第二种:幂等 TCC的两个阶段提交重试机制不会引发数据不一致,必须让TCC的两阶段Try,Confirm和Cancel接口保证幂等,这样不会重复使用或者释放资源。
- 第三种:悬挂 悬挂就是对于一个分布式事务,其两阶段Cancel接口比Try接口先执行。
优化方案
TAC-在开发,未发布
TAC
模式其实是TCC
模式的变种,顾名思义 TAC
模式被称为自动回滚,相比于 TCC
模式,用户完全不用关心 回滚方法如何去写,减少了用户的开发量,对用户完全透明。
TAC
模式只适合于关系型数据库。TAC
模式会拦截用户的SQL语句生成反向回滚SQL,SQL的兼容度也会是一大考验。
官方文档:https://dromara.org/zh-cn/docs/hmily/config.html
几个注解
@Hmily
/**
* The annotation Hmily.
*
* @author xiaoyu
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Hmily {
}
- 该注解为hmily分布式事务接口标识,表示该接口参与hmily分布式事务
@HmilyTCC
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface HmilyTCC {
/**
* Confirm method string.
*
* @return the string
*/
String confirmMethod() default "";
/**
* Cancel method string.
*
* @return the string
*/
String cancelMethod() default "";
/**
* Pattern pattern enum.
*
* @return the pattern enum
*/
TransTypeEnum pattern() default TransTypeEnum.TCC;
}
- 该注解为Hmily分布式事务TCC模式的切面(AOP point),可以标识在你本地具体实现方法上。
confirmMethod
: 注解标识方法的,确认方法名称,该方法参数列表与返回类型应与标识方法一致。cancelMethod
: 注解标识方法的,回滚方法名称,该方法参数列表与返回类型应与标识方法一致。
@HmilyTAC
/**
* The annotation HmilyTAC.
*
* @author xiaoyu
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface HmilyTAC {
}
- 该注解为Hmily分布式事务TAC模式的切面(AOP point),可以标识在你的本地方法具体实现上。
Demo
针对官方文档进行demo配置
步骤一: 引入依赖jar包
步骤二:引入hmily配置
步骤三:在具体的实现方法上(服务提供端),加上HmilyTCC or HmilyTAC 注解
步骤四:在feignClient调用方法上(消费方),加上Hmily
1.引入依赖
Spring-Namespace
- 引入依赖
<dependency>
<groupId>org.dromara</groupId>
<artifactId>hmily-springcloud</artifactId>
<version>{last.version}</version>
</dependency>
- 在xml中进行如下配置 ---经测试 使用报错 无法注入bean bean重复 故这个步骤不用
<!--配置扫码hmily框架的包-->
<context:component-scan base-package="org.dromara.hmily.*"/>
<!--设置开启aspectj-autoproxy-->
<aop:aspectj-autoproxy expose-proxy="true"/>
<!--配置Hmily启动的bean参数-->
<bean id="hmilyApplicationContextAware" class="org.dromara.hmily.spring.HmilyApplicationContextAware"/>
Spring-Boot-Starter
- 引入依赖
<dependency>
<groupId>org.dromara</groupId>
<artifactId>hmily-spring-boot-starter-springcloud</artifactId>
<version>{last.version}</version>
</dependency>
2.新增hmily配置
-
在项目的
resource
添加文件名为:hmily.yml
的配置文件hmily: server: configMode: local appName: order-motan # 如果server.configMode eq local 的时候才会读取到这里的配置信息. config: appName: order-motan serializer: kryo contextTransmittalMode: threadLocal scheduledThreadMax: 16 scheduledRecoveryDelay: 60 scheduledCleanDelay: 60 scheduledPhyDeletedDelay: 600 scheduledInitDelay: 30 recoverDelayTime: 60 cleanDelayTime: 180 limit: 200 retryMax: 10 bufferSize: 8192 consumerThreads: 16 asyncRepository: true autoSql: true phyDeleted: true storeDays: 3 repository: mysql repository: database: driverClassName: com.mysql.jdbc.Driver url : jdbc:mysql://127.0.0.1:3306/hmily?useUnicode=true&characterEncoding=utf8 username: root password: maxActive: 20 minIdle: 10 connectionTimeout: 30000 idleTimeout: 600000 maxLifetime: 1800000 file: path: prefix: /hmily mongo: databaseName: url: userName: password: zookeeper: host: localhost:2181 sessionTimeOut: 1000 rootPath: /hmily redis: cluster: false sentinel: false clusterUrl: sentinelUrl: masterName: hostName: port: password: maxTotal: 8 maxIdle: 8 minIdle: 2 maxWaitMillis: -1 minEvictableIdleTimeMillis: 1800000 softMinEvictableIdleTimeMillis: 1800000 numTestsPerEvictionRun: 3 testOnCreate: false testOnBorrow: false testOnReturn: false testWhileIdle: false timeBetweenEvictionRunsMillis: -1 blockWhenExhausted: true timeOut: 1000 metrics: metricsName: prometheus host: port: 9091 async: true threadCount : 16 jmxConfig:
3. 服务实现方添加注解
TCC模式
-
只需要在参与hmily分布式事务调用的具体实现方法上加
@HmilyTCC(confirmMethod = "confirm", cancelMethod = "cancel")
-
confirmMethod
: 确认方法名称,该方法参数列表与返回类型应与标识方法一致。 -
cancelMethod
: 回滚方法名称,该方法参数列表与返回类型应与标识方法一致。 -
TCC
模式应该保证confirm
和cancel
方法的幂等性,用户需要自行去开发这个2个方法,所有的事务的确认与回滚,完全由用户决定。Hmily框架只是负责来进行调用官网上有个没说 这个可以加一个注解 @Transactional(rollbackFor = Exception.class) //这个关系型数据库 自动回滚
public class HelloServiceImpl implements HelloService { @HmilyTCC(confirmMethod = "sayConfrim", cancelMethod = "sayCancel") @Transactional(rollbackFor = Exception.class) //这个必须要 public void say(String hello) { System.out.println("hello world"); } public void sayConfrim(String hello) { System.out.println(" confirm hello world"); } public void sayCancel(String hello) { System.out.println(" cancel hello world"); } }
TAC模式(在开发,未发布)
- 只需要在参与分布式事务调用的具体实现方法上加
@HmilyTAC
服务消费端(FeignClient)
- 在服务被调用方的
@FeignClient
接口方法上加上@Hmily
注解。
@FeignClient(value = "helle-service") public interface HelloService { @Hmily @RequestMapping("/helle-service/sayHello") void say(String hello); }
-
seata | hmily | 对比 |
---|---|---|
TCC | TCC | 基本相似,都需要自己写回滚或提交方法 |
TAC | XA,AT | 自动回滚,TAC (开发中,未开放);AT无侵入的分布式事务解决方案,适用于不希望对业务进行改造的场景,几乎0学习成本;XA模式是分布式强一致性的解决方案,但性能低而使用较少 |
SAGA | 长事务解决方案,适用于业务流程长且需要保证事务最终一致性的业务系统,Saga 模式一阶段就会提交本地事务,无锁,长流程情况下可以保证性能,多用于渠道层、集成层业务系统。事务参与者可能是其它公司的服务或者是遗留系统的服务,无法进行改造和提供 TCC 要求的接口,也可以使用 Saga 模式; |
注意:本文归作者所有,未经作者允许,不得转载