前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【云+社区年度征文】hmily之初识

【云+社区年度征文】hmily之初识

原创
作者头像
简单的程序员
修改2020-12-23 10:16:02
7630
修改2020-12-23 10:16:02
举报
文章被收录于专栏:奕仁专栏奕仁专栏

Hmily

hmily是什么

Hmily 全称 How much I love you . 意为“我多么爱你”,是不是很浪漫~ 作者(称他为宇哥)可能对感情比较专一,故命名为“hmily”。说完它的意义,那么它到底是做啥的呢?官方给的定义如下:Hmily是一款高性能,高可靠,易使用的柔性分布式事务解决方案,目前提供了对dubbo,spring-cloud,motan,grpc等rpc框架的支持,在易用性上提供零侵入性式的 Spring-Boot, Spring-Namespace 快速集成,目标是打造金融级的一体系分布式事务解决方案。当然,上面这个解释是官方定义的,我的理解,它是一款柔性的分布式事务解决方案,性能高不高,不是我说了算,而是得进行压测,后续会出这类压测的文章。

功能

  1. 高可靠性 :支持分布式场景下,事务异常回滚,超时异常恢复,防止事务悬挂
  2. 易用性 :提供零侵入性式的 Spring-Boot, Spring-Namespace 快速与业务系统集成
  3. 高性能 :去中心化设计,与业务系统完全融合,天然支持集群部署
  4. 可观测性 :Metrics多项指标性能监控,以及admin管理后台UI展示
  5. 多种RPC : 支持 Dubbo, SpringCloud,Motan, Sofa-rpc, brpc, tars 等知名RPC框架
  6. 日志存储 : 支持 mysql, oracle, mongodb, redis, zookeeper file 等方式,存储方式均使用异步
  7. 复杂场景 : 支持RPC嵌套调用事务

使用

RPC以springcloud为例,用简单的下单业务进行实验

springcloud demo注册中心使用eureka,eureka配置这里就不在赘述,搭建项目的代码可以去github下,这里也不在多余说

服务: 订单服务,账户服务,库存服务

首先配置这几个服务的配置文件

代码语言:javascript
复制
hmily:
  server:
    configMode: local
    appName: account-sc/order-sc/inventory-sc
  #  如果server.configMode eq local 的时候才会读取到这里的配置信息.
  config:
    appName: account-sc/order-sc/inventory-sc
    # 序列化方式 kryo会高一些
    serializer: kryo
    #上下文传输 默认使用局部线程
    contextTransmittalMode: threadLocal
    #定时任务线程池最大数
    scheduledThreadMax: 16
    #定时恢复事务时间(补偿) 默认60s跑一次
    scheduledRecoveryDelay: 60
    #定时清除事务日志时间
    scheduledCleanDelay: 60
    # 定时清理
    scheduledPhyDeletedDelay: 600
    scheduledInitDelay: 30
    #定时恢复事务时间(补偿)
    recoverDelayTime: 60
    cleanDelayTime: 180
  #查询limit
    limit: 200
    retryMax: 10
    bufferSize: 8192
    consumerThreads: 16
    #开启异步存储
    asyncRepository: true
    autoSql: true
    phyDeleted: true
    storeDays: 3
    #日志存储方式 本地文件
    repository: file

序列化除了kryo,同时还支持以下四种序列化方式

hessian,jdk,msgpack,protobuf

日志存储也可以使用database etcd mongodb redis zk

这里模拟几个场景:

  • 模拟下单付款操作在try阶段时候,账户rpc异常,此时订单状态会回滚,达到数据的一致性(注意:这里模拟的是系统异常,或者rpc异常
  • 模拟下单付款操作在try阶段时候,账户rpc超时异常(但是最后自身又成功了),此时订单状态会回滚,账户系统依赖自身的事务日志进行调度恢复,达到数据的一致性(异常指的是超时异常
  • 模拟下单付款操作在try阶段时候,库存异常,此时账户系统和订单状态会回滚,达到数据的一致性(注意:这里模拟的是系统异常,或者rpc异常)
  • 模拟下单付款操作在try阶段时候,库存超时异常(但是自身最后又成功了),此时账户系统和订单状态会回滚,(库存依赖事务日志进行恢复),达到数据的一致性(异常指的是超时异常)
  • 订单支付接口(里模拟的是rpc的嵌套调用 order--> account--> inventory, inventory异常情况

以第一个场景为例进行解析:

模拟下单付款操作在try阶段时候,账户rpc异常,此时订单状态会回滚,达到数据的一致性(注意:这里模拟的是系统异常,或者rpc异常

代码语言:javascript
复制
@Override
    @HmilyTCC(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
    public String mockPaymentAccountWithTryException(Order order) {
        updateOrderStatus(order, OrderStatusEnum.PAYING);
        //执行扣款超时   ---> 异常
        accountService.mockTryPaymentException(buildAccountDTO(order));
        return "success";
    }

下方是调用账户扣款服务超时的情况

代码语言:javascript
复制
  @Override
    @HmilyTCC(confirmMethod = "confirm", cancelMethod = "cancel")
    public boolean mockWithTryException(AccountDTO accountDTO) {
        throw new HmilyRuntimeException("账户扣减异常!");
    }

这里会报扣减库存的异常,调用完成之后然后我们再去数据库里面看订单和账户的数据,发现账户金额冻结了1000元,于是在等待了大约20秒的时候发现hmily会通过定时任务进行恢复数据,再一次查看的时候发现余额已经恢复为10000了

于是,最终数据都完成了一致性校验,但是可能会存在延迟的过程,通过查看源码看到它的自我恢复机制是通过用户手动去设置的,因此延迟问题完全可以避免,只不过是牺牲性能来换时间。

代码语言:javascript
复制
private void selfTccRecovery() {
    selfTccRecoveryExecutor
            .scheduleWithFixedDelay(() -> {
                try {
                    List<HmilyParticipant> hmilyParticipantList =
                            hmilyRepository.listHmilyParticipant(acquireDelayData(hmilyConfig.getRecoverDelayTime()), TransTypeEnum.TCC.name(), hmilyConfig.getLimit());
                       ...
                       //这里是通过方法调用来进行回滚的
                       if (Objects.isNull(globalHmilyTransaction)) {
                                tccRecovery(hmilyParticipant.getStatus(), hmilyParticipant);
                            } else {
                                tccRecovery(globalHmilyTransaction.getStatus(), hmilyParticipant);
                            }
                    }
                } catch (Exception e) {
                    LOGGER.error("hmily scheduled transaction log is error:", e);
                }
            }, hmilyConfig.getScheduledInitDelay(), hmilyConfig.getScheduledRecoveryDelay(), TimeUnit.SECONDS);
}
剖析它的日志存储模块

1、hmily的日志存储使用的是异步存储的,使用disruptor框架来实现异步的,那么这么做有什么好处?首先想到的是可以提高系统的吞吐量,可以充分利用cpu的性能,而且discruptor是可以实现秒级的到达率,据官网统计,它可以实现一秒几十万的并发,所以应用场景显而易见(秒杀,交易所);其次通过异步可以解耦代码,可以将发布者和实现者区分开。

微服务接入hmily 类图流程,如下图

hmily类图执行图
hmily类图执行图

由此可见,所有操作均在切面上进行,切面贯穿了所有服务之间的联系,以上流程可用时序图表示,如下图所示

分布式事务,TCC, SAGA, 柔性事务, 刚性事务详解_第3张图片
分布式事务,TCC, SAGA, 柔性事务, 刚性事务详解_第3张图片

图片摘选自 分布式事务

看到上面的流程图,有没有对hmily有一个简单的认识?如果没有,那我的这篇文章就太失败辣!我就得考虑重新编辑咯>

Hmily,曾经有一份真挚的感情摆在我的面前,而我却选择了代码,现在我也不后悔,因为我是年轻人,我讲“码德”!

谢谢您的浏览,我叫奕仁,人人都是产品经理后端开发

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Hmily
    • hmily是什么
      • 功能
        • 使用
          • RPC以springcloud为例,用简单的下单业务进行实验
          • 剖析它的日志存储模块
          • 微服务接入hmily 类图流程,如下图
      相关产品与服务
      对象存储
      对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档