可编程最终一致工作流

Posted 海边散步的鱼技术笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可编程最终一致工作流相关的知识,希望对你有一定的参考价值。

前言

在分布式事务中,经常需要开发一个复杂的业务流程。这个流程通常会涉及到多个服务的调用,并且流程对各服务的调用结果的一致性有要求。比如在还款流程中,贷款的账务与用户的支付,以及合作渠道的账务就是如此,开发这样的流程,并且处理每个服务调用可能异常的情况,还需要保证最终一致性场景,这里简单介绍可项目组内使用的可编程最终一致工作流本文简单做了笔记介绍,也参考其他资料,若有不足,期待帮忙纠正和完善。

开场

服务处理经常会碰到各个服务调用的异常处理没有统一规范:比如某个依赖接口幂等处理不规范,当服务调用超时的时候,需要使用查询接口来拿到结果;且需要间隔3s后才能通过查询接口拿到结果。对于以上一致性业务流程,业内有一些解决方案。

方法1:使用定时任务补偿:需要额外维护状态流转,补偿逻辑维护复杂,难以维护。

方法2:使用MQ通知下游适合简单的松耦合的业务逻辑,不适合复杂逻辑;且数据可能丢失,很多重复处理MQ消息的冗余逻辑。

• 方法3:事务消息可以保证数据不可丢,适合简单的业务逻辑,但不适合复杂流程。

• 方法4: TCC方案:需要各服务接口都按照TCC的协议,复杂的逻辑套用TCC比较麻烦,尤其当已有的依赖接口并不遵守TCC方案的协议。

我们需要一个方案,能帮忙开发者从关注流程中各种异常处理的补偿逻辑中脱离出来,开发者只需关心流程逻辑本身,诞生出一个轻量级的分布式柔性事务组件(可编程一致性工作流组件),目前由目前项目组组长发起并创始,项目组内落地和在迭代优化,网上也有类似的架构设计组件,简单介绍一下,互相学习分享

主要特点

可编程一致性工作流组件,适用于布式环境中较复杂的业务流程。可以在各种异常的情况下,保证结果的最终一致性。其组件将各种异常处理的补偿逻辑抽象出来,开发者只需关心流程本身。核心理念包括几个部分:

工作流模型:业务流程被映射成一颗工作流。工作流上每个节点都向消息总线发送消息。消息总线路由消息到对应节点来处理。

可靠的消息总线:通过综合运用数据库,内存队列和MQ延迟队列,消息总线能够保证消息一定会被处理。

灵活的工作流编排:借鉴了流式编程的想法,设计了一些基本的工作流原语,可以方便的通过代码实现一颗工作流。

使用此的方案,开发者只需关注利用工作流原语搭建工作流本身,以及工作流每个节点的业务逻辑,无需再操心各种异常的补偿逻辑。

核心组件

•  event bus: 消息总线,负责消息的发布,订阅。综合使用 内存队列,mysql和MQ延迟队列来保障消息可靠处理的同时,兼顾效率(节省不必要的消息进入MQ)。

  event executor: 工作流节点。工作流将由多个节点组合。节点向消息总线发送事件,并监听消息总线。

  router:工作流节点的路由。

•  poller:处理结果通知,满足需要同步获得工作流处理结果的需求。

•  flow builder:将开发者工作流的原语(顺序,分支,调用),翻译成一系列工作流的节点。

总结:开发者通过工作流的原语(顺序,分支,调用)搭建工作流,flow builder将其翻译成一系列工作流的节点,注册在 event bus上。然后消息通过 router路由到各节点。程序可以向工作流提交消息,返回或者同步等待poller获得工作流处理的结果。

目前功能

支持memory和redis ,mq类型消息总线

支持mysql消息存储

工作流构建和运行

响应式创建工作流的GraphEntry

spring配置工具

当更新消息发生异常时,目前依赖于重试任务重新捞取消息.是否可以实时给调用回复。

当确认消息发生异常时,是否能保证后面补偿是对的。包括重新发布消息。

异步确认线程数,支持配置。

重试时间或queue数量大于一定限度时,是否可以落库,以避免内存中消息对可用性的影响。

表可以隔离。目前通过事件分组隔离。后续支持表级别能隔离。

不允许读写分离,强依赖主库

预留shardingkey,可以分表分库。

sync 特性:返回结果可以直接拿到结果。

支持spring configuration配置

支持并行化调度


声明:本文主要是工作整理笔记用,其中内容参考和引用了其他的文章,重点只在帮大家整理资料和知识分享用,若有不足,期待帮忙纠正和完善,谢谢。

以上是关于可编程最终一致工作流的主要内容,如果未能解决你的问题,请参考以下文章

最终一致分布式事务方案解析

补偿交易模式

基于Redis实现分布式锁-Redisson使用及源码分析面试+工作

软件工程个人最终总结

CRM 2011,以编程方式停止自定义工作流程

Go并发编程之传统同步—互斥锁