分布式事务——hmily主流程源码分析

分布式事务——hmily主流程源码分析

1. 前提

以上一篇《分布式事务——Dubbo集成hmily使用》为例,RPC框架为Apache DubboTCC分布式事务模式,进行hmily分布式事务主流程源码分析。hmily版本2.2.1

项目maven依赖:

<dependency>
    <groupId>org.dromara</groupId>
    <artifactId>hmily-spring-boot-starter-apache-dubbo</artifactId>
</dependency>

2. 主流程图

在这里插入图片描述

3. 源码分析

1. 自动化配置

hmily-spring-boot-starter-parent

HmilyAutoConfiguration

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class HmilyAutoConfiguration {
    
    /**
     * 分布式事务注解切面逻辑
     */
    @Bean
    public SpringHmilyTransactionAspect hmilyTransactionAspect() {
        return new SpringHmilyTransactionAspect();
    }
    
    /**
     * 存储Dubbo RPC的字段实例
     */
    @Bean
    @ConditionalOnProperty(value = "hmily.support.rpc.annotation", havingValue = "true")
    public BeanPostProcessor refererAnnotationBeanPostProcessor() {
        return new RefererAnnotationBeanPostProcessor();
    }
    
    /**
     * hmily需要的资源启动类
     */
    @Bean
    @Qualifier("hmilyTransactionBootstrap")
    @Primary
    public HmilyApplicationContextAware hmilyTransactionBootstrap() {
        return new HmilyApplicationContextAware();
    }
}

2. 注解切面逻辑

hmily分布式事务的主体流程主要在SpringHmilyTransactionAspect

AbstractHmilyTransactionAspect

@Aspect
public abstract class AbstractHmilyTransactionAspect {

    private final HmilyTransactionInterceptor interceptor = new HmilyGlobalInterceptor();

    /**
     * @HmilyTCC/@HmilyTAC注解生效
     */
    @Pointcut("@annotation(org.dromara.hmily.annotation.HmilyTCC) || @annotation(org.dromara.hmily.annotation.HmilyTAC)")
    public void hmilyInterceptor() {
    }

    @Around("hmilyInterceptor()")
    public Object interceptTccMethod(final ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        return interceptor.interceptor(proceedingJoinPoint);
    }
}

HmilyTransactionInterceptor

public class HmilyGlobalInterceptor implements HmilyTransactionInterceptor {

    /**
     * Apache Dubbo实现
     * {@link org.dromara.hmily.dubbo.parameter.DubboParameterLoader}
     */
    private static RpcParameterLoader parameterLoader;

    static {
        parameterLoader = Optional.ofNullable(ExtensionLoaderFactory.load(RpcParameterLoader.class)).orElse(new LocalParameterLoader());
    }

    @Override
    public Object interceptor(final ProceedingJoinPoint pjp) throws Throwable {
        // 构建HmilyTransactionContext,Apache Dubbo的实现为RpcContext.getContext()::getAttachment获取RPC上下文
        HmilyTransactionContext context = parameterLoader.load();
        // 返回处理类处理后的结果
        return HmilyTransactionAspectInvoker.getInstance().invoke(context, pjp);
    }
}

interceptor()中根据SPI机制获取RpcParameterLoader实现类,调用实现类中的load()获取HmilyTransactionContext,做为参数传入处理类。

RpcParameterLoaderApache Dubbo中的实现类为DubboParameterLoader,从RPC上下文中获取参数

DubboParameterLoader

@HmilySPI(value = "dubbo")
public class DubboParameterLoader implements RpcParameterLoader {

    @Override
    public HmilyTransactionContext load() {
        return Optional.ofNullable(RpcMediator.getInstance().acquire(RpcContext.getContext()::getAttachment)).orElse(HmilyContextHolder.get());
    }
}

RpcMediator.getInstance().acquire()作用是构建HmilyTransactionContext

public HmilyTransactionContext acquire(final RpcAcquire rpcAcquire) {
    HmilyTransactionContext hmilyTransactionContext = null;
    // 从Rpc上下文中获取参数_HMILY_TRANSACTION_CONTEXT值
    final String context = rpcAcquire.acquire(CommonConstant.HMILY_TRANSACTION_CONTEXT);
    if (StringUtils.isNoneBlank(context)) {
        // string转为HmilyTransactionContext对象
        hmilyTransactionContext = GsonUtils.getInstance().fromJson(context, HmilyTransactionContext.class);
    }
    return hmilyTransactionContext;
}

HmilyTransactionAspectInvoker.invoke():选择TCC \ TAC处理类处理

public Object invoke(final HmilyTransactionContext hmilyTransactionContext, final ProceedingJoinPoint point) throws Throwable {
    MethodSignature signature = (MethodSignature) point.getSignature();
    Method method = signature.getMethod();
    final HmilyTCC hmilyTCC = method.getAnnotation(HmilyTCC.class);
    if (null != hmilyTCC) {
        // 获取处理类后调用handler方法处理
        return FACTORY_MAP.get(TransTypeEnum.TCC).factoryOf(hmilyTransactionContext).handler(point, hmilyTransactionContext);
    } else {
        return FACTORY_MAP.get(TransTypeEnum.TAC).factoryOf(hmilyTransactionContext).handler(point, hmilyTransactionContext);
    }
}

AbstractHmilyTransactionHandlerFactory.factoryOf()

/**
 * 根据事务的角色选择处理类
 */
@Override
public HmilyTransactionHandler factoryOf(final HmilyTransactionContext context) {
    if (Objects.isNull(context)) {
        return getMap().get(HmilyRoleEnum.START);
    } else {
        // if context not null and role is inline  is ParticipantHmilyTransactionHandler.
        if (context.getRole() == HmilyRoleEnum.LOCAL.getCode()) {
            return getMap().get(HmilyRoleEnum.LOCAL);
        } else if (context.getRole() == HmilyRoleEnum.PARTICIPANT.getCode()
                   || context.getRole() == HmilyRoleEnum.START.getCode()) {
            return getMap().get(HmilyRoleEnum.PARTICIPANT);
        }
        return getMap().get(HmilyRoleEnum.CONSUMER);
    }
}

TCC模式处理类HmilyTccTransactionHandlerFactory

@HmilySPI("tcc")
public class HmilyTccTransactionHandlerFactory extends AbstractHmilyTransactionHandlerFactory {

    private static final Map<HmilyRoleEnum, HmilyTransactionHandler> HANDLER_MAP = new EnumMap<>(HmilyRoleEnum.class);

    static {
        // 根据事务角色选择逻辑处理类
        HANDLER_MAP.put(HmilyRoleEnum.START, new StarterHmilyTccTransactionHandler());
        HANDLER_MAP.put(HmilyRoleEnum.PARTICIPANT, new ParticipantHmilyTccTransactionHandler());
        HANDLER_MAP.put(HmilyRoleEnum.CONSUMER, new ConsumeHmilyTccTransactionHandler());
        HANDLER_MAP.put(HmilyRoleEnum.LOCAL, new LocalHmilyTccTransactionHandler());
    }

    @Override
    protected Map<HmilyRoleEnum, HmilyTransactionHandler> getMap() {
        return HANDLER_MAP;
    }
}

这里只分析事务发起者处理类StarterHmilyTccTransactionHandler和事务参与者处理类ParticipantHmilyTccTransactionHandler

3. 事务发起者处理器StarterHmilyTccTransactionHandler

StarterHmilyTccTransactionHandler.handler()

@Override
public Object handler(final ProceedingJoinPoint point, final HmilyTransactionContext context)
    throws Throwable {
    Object returnValue;
    Supplier<Boolean> histogramSupplier = null;
    // 指标数据相关
    Optional<MetricsHandlerFacade> handlerFacade = MetricsHandlerFacadeEngine.load();
    try {
        if (handlerFacade.isPresent()) {
            handlerFacade.get().counterIncrement(MetricsLabelEnum.TRANSACTION_TOTAL.getName(), TransTypeEnum.TCC.name());
            histogramSupplier = handlerFacade.get().histogramStartTimer(MetricsLabelEnum.TRANSACTION_LATENCY.getName(), TransTypeEnum.TCC.name());
        }
        // 构建HmilyTransactionContext等
        HmilyTransaction hmilyTransaction = executor.preTry(point);
        try {
            //execute try
            // 执行try方法
            returnValue = point.proceed();
            hmilyTransaction.setStatus(HmilyActionEnum.TRYING.getCode());
            // 更新发布者状态,并查询参与者及更新状态
            executor.updateStartStatus(hmilyTransaction);
        } catch (Throwable throwable) {
            //if exception ,execute cancel
            final HmilyTransaction currentTransaction = HmilyTransactionHolder.getInstance().getCurrentTransaction();
            disruptorProviderManage.getProvider().onData(() -> {
                handlerFacade.ifPresent(metricsHandlerFacade -> metricsHandlerFacade.counterIncrement(MetricsLabelEnum.TRANSACTION_STATUS.getName(),
                                                                                                      TransTypeEnum.TCC.name(), HmilyRoleEnum.START.name(), HmilyActionEnum.CANCELING.name()));
                // 有异常进行全局回滚
                executor.globalCancel(currentTransaction);
            });
            throw throwable;
        }
        //execute confirm
        final HmilyTransaction currentTransaction = HmilyTransactionHolder.getInstance().getCurrentTransaction();
        disruptorProviderManage.getProvider().onData(() -> {
            handlerFacade.ifPresent(metricsHandlerFacade -> metricsHandlerFacade.counterIncrement(MetricsLabelEnum.TRANSACTION_STATUS.getName(),
                                                                                                  TransTypeEnum.TCC.name(), HmilyRoleEnum.START.name(), HmilyActionEnum.CONFIRMING.name()));
            // 执行全局confirm()
            executor.globalConfirm(currentTransaction);
        });
    } finally {
        HmilyContextHolder.remove();
        executor.remove();
        if (null != histogramSupplier) {
            histogramSupplier.get();
        }
    }
    return returnValue;
}

步骤:

  1. executor.preTry()中构建HmilyTransaction、HmilyTransactionContext等;
  2. 执行发起者的try()
  3. try()执行成功,更新事务状态,异步执行全局confirm()
  4. try()执行异常,异步执行全局cancel()

HmilyTccTransactionExecutor.preTry()

public HmilyTransaction preTry(final ProceedingJoinPoint point) {
    LogUtil.debug(LOGGER, () -> "......hmily tcc transaction starter....");
    // 构建HmilyTransaction
    HmilyTransaction hmilyTransaction = createHmilyTransaction();
    // HmilyRepositoryEventPublisher发布 创建全局事务事件
    HmilyRepositoryStorage.createHmilyTransaction(hmilyTransaction);
    // 构建事务参与者
    HmilyParticipant hmilyParticipant = buildHmilyParticipant(point, null, null, HmilyRoleEnum.START.getCode(), hmilyTransaction.getTransId());
    // HmilyRepositoryEventPublisher发布 创建参与者事件
    HmilyRepositoryStorage.createHmilyParticipant(hmilyParticipant);
    // 参与者加入到全局事务HmilyTransaction中
    hmilyTransaction.registerParticipant(hmilyParticipant);
    // 保存HmilyTransaction到ThreadLocal中
    HmilyTransactionHolder.getInstance().set(hmilyTransaction);
    // 构建HmilyTransactionContext
    HmilyTransactionContext context = new HmilyTransactionContext();
    context.setAction(HmilyActionEnum.TRYING.getCode());
    context.setTransId(hmilyTransaction.getTransId());
    context.setRole(HmilyRoleEnum.START.getCode());
    context.setTransType(TransTypeEnum.TCC.name());
    // 保存HmilyTransactionContext到HmilyContextHolder
    HmilyContextHolder.set(context);
    return hmilyTransaction;
}

HmilyTccTransactionExecutor.updateStartStatus():更新事务状态

public void updateStartStatus(final HmilyTransaction hmilyTransaction) {
    // HmilyRepositoryEventPublisher更新全局事务状态
    HmilyRepositoryStorage.updateHmilyTransactionStatus(hmilyTransaction);
    // 筛选出发起者
    HmilyParticipant hmilyParticipant = filterStartHmilyParticipant(hmilyTransaction);
    if (Objects.nonNull(hmilyParticipant)) {
        // 更新发起者状态
        hmilyParticipant.setStatus(hmilyTransaction.getStatus());
        // HmilyRepositoryEventPublisher更新参与者状态
        HmilyRepositoryStorage.updateHmilyParticipantStatus(hmilyParticipant);
    }
}

HmilyTccTransactionExecutor.globalConfirm():执行全局confirm()

public void globalConfirm(final HmilyTransaction currentTransaction) throws HmilyRuntimeException {
    LogUtil.debug(LOGGER, () -> "hmily transaction confirm .......!start");
    if (Objects.isNull(currentTransaction) || CollectionUtils.isEmpty(currentTransaction.getHmilyParticipants())) {
        return;
    }
    // 当前事务状态更新为CONFIRMING
    currentTransaction.setStatus(HmilyActionEnum.CONFIRMING.getCode());
    // 更新全局事务状态
    HmilyRepositoryStorage.updateHmilyTransactionStatus(currentTransaction);
    final List<HmilyParticipant> hmilyParticipants = currentTransaction.getHmilyParticipants();
    List<Boolean> successList = new ArrayList<>();
    // 循环参与者,执行confirm()方法
    for (HmilyParticipant hmilyParticipant : hmilyParticipants) {
        try {
            if (hmilyParticipant.getRole() == HmilyRoleEnum.START.getCode()) {
                HmilyReflector.executor(HmilyActionEnum.CONFIRMING, ExecutorTypeEnum.LOCAL, hmilyParticipant);
                HmilyRepositoryStorage.removeHmilyParticipant(hmilyParticipant);
            } else {
                HmilyReflector.executor(HmilyActionEnum.CONFIRMING, ExecutorTypeEnum.RPC, hmilyParticipant);
            }
            successList.add(true);
        } catch (Throwable e) {
            successList.add(false);
            LOGGER.error("HmilyParticipant confirm exception param:{} ", hmilyParticipant.toString(), e);
        } finally {
            HmilyContextHolder.remove();
        }
    }
    if (successList.stream().allMatch(e -> e)) {
        // remove global
        // 删除全局日志
        HmilyRepositoryStorage.removeHmilyTransaction(currentTransaction);
    }
}

这里根据参与者的角色,如果是START(发起者),则使用反射调用本地方法;如果是其他角色,则进行RPC远程调用;

HmilyReflector.executor()

public static Object executor(final HmilyActionEnum action, final ExecutorTypeEnum executorType, final HmilyParticipant hmilyParticipant) throws Exception {
    if (executorType == ExecutorTypeEnum.RPC && hmilyParticipant.getRole() != HmilyRoleEnum.START.getCode()) {
        setContext(action, hmilyParticipant);
        // 执行RPC调用的confirm()或cancel()
        if (action == HmilyActionEnum.CONFIRMING) {
            return executeRpc(hmilyParticipant.getConfirmHmilyInvocation());
        } else {
            return executeRpc(hmilyParticipant.getCancelHmilyInvocation());
        }
    } else {
        if (action == HmilyActionEnum.CONFIRMING) {
            return executeLocal(hmilyParticipant.getConfirmHmilyInvocation(), hmilyParticipant.getTargetClass(), hmilyParticipant.getConfirmMethod());
        } else {
            return executeLocal(hmilyParticipant.getConfirmHmilyInvocation(), hmilyParticipant.getTargetClass(), hmilyParticipant.getCancelMethod());
        }
    }
}

HmilyTccTransactionExecutor.globalCancel():执行全局cancel()

public void globalCancel(final HmilyTransaction currentTransaction) {
    LogUtil.debug(LOGGER, () -> "tcc cancel ...........start!");
    if (Objects.isNull(currentTransaction) || CollectionUtils.isEmpty(currentTransaction.getHmilyParticipants())) {
        return;
    }
    // 更新当前事务状态CANCELING
    currentTransaction.setStatus(HmilyActionEnum.CANCELING.getCode());
    //update cancel
    HmilyRepositoryStorage.updateHmilyTransactionStatus(currentTransaction);
    final List<HmilyParticipant> hmilyParticipants = currentTransaction.getHmilyParticipants();
    // 循环参与者进行回滚
    for (HmilyParticipant hmilyParticipant : hmilyParticipants) {
        try {
            if (hmilyParticipant.getRole() == HmilyRoleEnum.START.getCode()) {
                HmilyReflector.executor(HmilyActionEnum.CANCELING, ExecutorTypeEnum.LOCAL, hmilyParticipant);
                HmilyRepositoryStorage.removeHmilyParticipant(hmilyParticipant);
            } else {
                HmilyReflector.executor(HmilyActionEnum.CANCELING, ExecutorTypeEnum.RPC, hmilyParticipant);
            }
        } catch (Throwable e) {
            LOGGER.error("HmilyParticipant cancel exception :{}", hmilyParticipant.toString(), e);
        } finally {
            HmilyContextHolder.remove();
        }
    }
}

4. 事务参与者处理器ParticipantHmilyTccTransactionHandler

ParticipantHmilyTccTransactionhandler.handler()

public Object handler(final ProceedingJoinPoint point, final HmilyTransactionContext context) throws Throwable {
    HmilyParticipant hmilyParticipant = null;
    switch (HmilyActionEnum.acquireByCode(context.getAction())) {
        case TRYING:
            try {
                hmilyParticipant = executor.preTryParticipant(context, point);
                final Object proceed = point.proceed();
                hmilyParticipant.setStatus(HmilyActionEnum.TRYING.getCode());
                //update log status to try
                HmilyRepositoryStorage.updateHmilyParticipantStatus(hmilyParticipant);
                return proceed;
            } catch (Throwable throwable) {
                //if exception ,delete log.
                if (Objects.nonNull(hmilyParticipant)) {
                    HmilyParticipantCacheManager.getInstance().removeByKey(hmilyParticipant.getParticipantId());
                }
                HmilyRepositoryStorage.removeHmilyParticipant(hmilyParticipant);
                throw throwable;
            } finally {
                HmilyContextHolder.remove();
            }
        case CONFIRMING:
            MetricsHandlerFacadeEngine.load().ifPresent(metricsHandlerFacade -> metricsHandlerFacade.counterIncrement(MetricsLabelEnum.TRANSACTION_STATUS.getName(),
                                                                                                                      TransTypeEnum.TCC.name(), HmilyRoleEnum.PARTICIPANT.name(), HmilyActionEnum.CONFIRMING.name()));
            List<HmilyParticipant> confirmList = HmilyParticipantCacheManager.getInstance().get(context.getParticipantId());
            return executor.participantConfirm(confirmList, context.getParticipantId());
        case CANCELING:
            MetricsHandlerFacadeEngine.load().ifPresent(metricsHandlerFacade -> metricsHandlerFacade.counterIncrement(MetricsLabelEnum.TRANSACTION_STATUS.getName(),
                                                                                                                      TransTypeEnum.TCC.name(), HmilyRoleEnum.PARTICIPANT.name(), HmilyActionEnum.CANCELING.name()));
            List<HmilyParticipant> cancelList = HmilyParticipantCacheManager.getInstance().get(context.getParticipantId());
            return executor.participantCancel(cancelList, context.getParticipantId());
        default:
            break;
    }
    Method method = ((MethodSignature) (point.getSignature())).getMethod();
    return DefaultValueUtils.getDefaultValue(method.getReturnType());
}

根据上下文中全局事务的状态选择调用try()\confirm()\cancel().

5. 上述就是hmily分布式事务的主体逻辑

6. 资源启动类HmilyApplicationContextAware

HmilyApplicationContextAware

public class HmilyApplicationContextAware implements ApplicationContextAware {

    @Override
    public void setApplicationContext(@NonNull final ApplicationContext applicationContext) throws BeansException {
        // ApplicationContext设置到SpringBeanUtils中
        SpringBeanUtils.INSTANCE.setCfgContext((ConfigurableApplicationContext) applicationContext);
        // SpringBeanProvide设置到SingletonHolder.SINGLES存储
        SingletonHolder.INST.register(ObjectProvide.class, new SpringBeanProvide());
        // 应用启动
        HmilyBootstrap.getInstance().start();
    }
}

HmilyBootstrap

public void start() {
    try {
        // 加载配置保存到ConfigEnv中
        ConfigLoaderServer.load();
        // 获取配置类
        HmilyConfig hmilyConfig = ConfigEnv.getInstance().getConfig(HmilyConfig.class);
        // 校验是否配置了appName
        check(hmilyConfig);
        // 前面已经设置了SpringBeanProvide,所以不会设置ReflectObject
        registerProvide();
        // 加载事务日志存储操作实现类,并存储到HmilyRepositoryFacade
        loadHmilyRepository(hmilyConfig);
        // 保存到HmilyShutdownHook中,当应用关闭时,调用这个实例的close()
        registerAutoCloseable(new HmilyTransactionSelfRecoveryScheduled(), HmilyRepositoryEventPublisher.getInstance());
        // 指标初始化
        initMetrics();
    } catch (Exception e) {
        LOGGER.error(" hmily init exception:", e);
        System.exit(0);
    }
    // 打印logo
    new HmilyLogo().logo();
}

private void loadHmilyRepository(final HmilyConfig hmilyConfig) {
    // 通过SPI机制获取HmilySerializer和HmilyRepository实现类
    HmilySerializer hmilySerializer = ExtensionLoaderFactory.load(HmilySerializer.class, hmilyConfig.getSerializer());
    HmilyRepository hmilyRepository = ExtensionLoaderFactory.load(HmilyRepository.class, hmilyConfig.getRepository());
    hmilyRepository.setSerializer(hmilySerializer);
    // 初始化HmilyRepository
    hmilyRepository.init(buildAppName(hmilyConfig));
    // HmilyRepository设置到HmilyRepositoryFacade做为属性
    HmilyRepositoryFacade.getInstance().setHmilyRepository(hmilyRepository);
}

hmily的资源启动类主要做:

  1. 加载配置;
  2. 通过SPI机制将事务日志存储实现类设置到HmilyRepositoryFacade;

7. RPC接口实例存储RefererAnnotationBeanPostProcessor

RefererAnnotationBeanPostProcessor:通过SPI机制找到AnnotationField实现类,将通过条件的字段保存到SingletonHolder

private static AnnotationField annotationField;
    
static {
    annotationField = Optional.ofNullable(ExtensionLoaderFactory.load(AnnotationField.class)).orElse(new DefaultAnnotationField());
}

@Override
public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
    Class<?> clazz = bean.getClass();
    if (isProxyBean(bean)) {
        clazz = AopUtils.getTargetClass(bean);
    }
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
        try {
            // 字段中是否带有@Reference注解
            if (annotationField.check(field)) {
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }
                Object ref = field.get(bean);
                Class<?> refClass = field.getType();
                Method[] methods = refClass.getMethods();
                boolean anyMatch = Stream.of(methods).anyMatch(method -> Objects.nonNull(method.getAnnotation(Hmily.class)));
                if (anyMatch) {
                    // 带有Hmily注解的字段实例保存到SingletonHolder.SINGLES
                    SingletonHolder.INST.register(field.getType(), ref);
                }
            }
        } catch (Exception e) {
            throw new BeanInitializationException("Failed to init spring bean at filed " + field.getName()
                                                  + " in class " + bean.getClass().getName(), e);
        }
    }
    return bean;
}

DubboRefererAnnotationField:AnnotationField在Apche Dubbo的实现类

@HmilySPI(value = "dubbo")
public class DubboRefererAnnotationField implements AnnotationField {

    @Override
    public boolean check(final Field field) {
        Reference reference = field.getAnnotation(Reference.class);
        return reference != null;
    }
}

8. 事务日志存储

在事务状态变更,创建事务参与者等操作中,都有涉及到HmilyRepositoryStorage。该类的功能是发送事务日志事件,异步消费日志进行对应的存储。这里存储以MySQL,事件以创建全局事务为例

HmilyRepositoryStorage.createHmilyTransaction()

private static final HmilyRepositoryEventPublisher PUBLISHER = HmilyRepositoryEventPublisher.getInstance();

/**
 * Create hmily transaction.
 */
public static void createHmilyTransaction(final HmilyTransaction hmilyTransaction) {
    if (Objects.nonNull(hmilyTransaction)) {
        PUBLISHER.publishEvent(hmilyTransaction, EventTypeEnum.CREATE_HMILY_TRANSACTION.getCode());
    }
}

HmilyRepositoryEventPublisher.publishEvent()

private DisruptorProviderManage<HmilyRepositoryEvent> disruptorProviderManage;

public void publishEvent(final HmilyTransaction hmilyTransaction, final int type) {
    // 构建事件消息载体
    HmilyRepositoryEvent event = new HmilyRepositoryEvent();
    event.setType(type);
    event.setHmilyTransaction(hmilyTransaction);
    event.setTransId(hmilyTransaction.getTransId());
    // 推送事件到disruptor
    push(event);
}

private void push(final HmilyRepositoryEvent event) {
    // 默认异步执行
    if (Objects.nonNull(hmilyConfig) && hmilyConfig.isAsyncRepository()) {
        disruptorProviderManage.getProvider().onData(event);
    } else {
        HmilyRepositoryDispatcher.getInstance().doDispatcher(event);
    }
}

DisruptorProvider<T>.onData()

public void onData(final T t) {
    long position = ringBuffer.next();
    try {
        DataEvent<T> de = ringBuffer.get(position);
        de.setT(t);
        ringBuffer.publish(position);
    } catch (Exception ex) {
        logger.error("push data error:", ex);
    }
}

有了disruptor事件,生产者,还差消费者

DisruptorConsumer<T>实现disruptor框架的WorkHandler接口,做为一个代理类,实际处理交由DisruptorConsumerFactory.executor()执行

DisruptorConsumer

public class DisruptorConsumer<T> implements WorkHandler<DataEvent<T>> {

    private DisruptorConsumerFactory<T> factory;

    DisruptorConsumer(final DisruptorConsumerFactory<T> factory) {
        this.factory = factory;
    }

    @Override
    public void onEvent(final DataEvent<T> t) {
        if (t != null) {
            factory.create().executor(t.getT());
        }
    }
}

HmilyRepositoryDataHandler.executor():通过负载均衡算法选择线程,执行HmilyRepositoryDispatcher.doDispatcher()

public void executor(final HmilyRepositoryEvent event) {
    Long transId = event.getTransId();
    executor.select(String.valueOf(transId)).execute(() -> {
        HmilyRepositoryDispatcher.getInstance().doDispatcher(event);
        event.clear();
    });

}

HmilyRepositoryDispatcher.doDispatcher():通过事件类型,调用日志存储类执行相应操作

public void doDispatcher(final HmilyRepositoryEvent event) {
    EventTypeEnum eventTypeEnum = EventTypeEnum.buildByCode(event.getType());
    HmilyTransaction hmilyTransaction = event.getHmilyTransaction();
    HmilyParticipant hmilyParticipant = event.getHmilyParticipant();
    HmilyParticipantUndo hmilyParticipantUndo = event.getHmilyParticipantUndo();
    switch (eventTypeEnum) {
        case CREATE_HMILY_TRANSACTION:
            HmilyRepositoryFacade.getInstance().createHmilyTransaction(event.getHmilyTransaction());
            break;
        case REMOVE_HMILY_TRANSACTION:
            HmilyRepositoryFacade.getInstance().removeHmilyTransaction(hmilyTransaction.getTransId());
            break;
        case UPDATE_HMILY_TRANSACTION_STATUS:
            HmilyRepositoryFacade.getInstance().updateHmilyTransactionStatus(hmilyTransaction.getTransId(), hmilyTransaction.getStatus());
            break;
        case CREATE_HMILY_PARTICIPANT:
            HmilyRepositoryFacade.getInstance().createHmilyParticipant(event.getHmilyParticipant());
            break;
        case UPDATE_HMILY_PARTICIPANT_STATUS:
            HmilyRepositoryFacade.getInstance().updateHmilyParticipantStatus(hmilyParticipant.getParticipantId(), hmilyParticipant.getStatus());
            break;
        case REMOVE_HMILY_PARTICIPANT:
            HmilyRepositoryFacade.getInstance().removeHmilyParticipant(hmilyParticipant.getParticipantId());
            break;
        case CREATE_HMILY_PARTICIPANT_UNDO:
            HmilyRepositoryFacade.getInstance().createHmilyParticipantUndo(hmilyParticipantUndo);
            break;
        case REMOVE_HMILY_PARTICIPANT_UNDO:
            HmilyRepositoryFacade.getInstance().removeHmilyParticipantUndo(hmilyParticipantUndo.getUndoId());
            break;
        default:
            break;
    }
}

HmilyRepositoryFacade:日志存储门面,由HmilyRepository具体执行,而在资源启动类(HmilyBootstrap)中通过SPI机制将HmilyRepository的实现类set进去了

HmilyRepositoryFacade.createHmilyTransaction()

/**
 *创建事务
 */
public void createHmilyTransaction(final HmilyTransaction hmilyTransaction) {
    checkRows(hmilyRepository.createHmilyTransaction(hmilyTransaction));
}

MySQL存储为例,实现类为AbstractHmilyDatabase

AbstractHmilyDatabase.createHmilyTransaction()

/**
 * The constant INSERT_HMILY_TRANSACTION.
 */
    protected static final String INSERT_HMILY_TRANSACTION = "INSERT INTO hmily_transaction_global (trans_id, app_name, status, trans_type, "
            + "retry, version, create_time, update_time) VALUES(?, ?, ?, ?, ?, ?, ?, ?)";

@Override
public int createHmilyTransaction(final HmilyTransaction hmilyTransaction) {
    return executeUpdate(INSERT_HMILY_TRANSACTION, hmilyTransaction.getTransId(), appName, hmilyTransaction.getStatus(),
                         hmilyTransaction.getTransType(), hmilyTransaction.getRetry(), hmilyTransaction.getVersion(), hmilyTransaction.getCreateTime(), hmilyTransaction.getUpdateTime());
}

private int executeUpdate(final String sql, final Object... params) {
    try (Connection con = dataSource.getConnection();
         PreparedStatement ps = createPreparedStatement(con, sql, params)) {
        return ps.executeUpdate();
    } catch (SQLException e) {
        log.error("hmily jdbc executeUpdate repository exception -> ", e);
        return FAIL_ROWS;
    }
}

4.总结

上述通过源码分析了hmily分布式事务的主体流程,没有对源码设计进行详细分析,其中涉及很多的设计模式、SPI机制等好的设计。在接下来的文章中进行分析。



世界那么大,感谢遇见,未来可期…

欢迎同频共振的那一部分人

Tarzan写bug

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值