分布式事务一致性,事务补偿实战

一、事务记录补偿表设计

三、业务补偿函数

@Override
    public void compensation(BidPaymentDetailConfirmRecord confirmRecord, ProviderUserSession userSession) throws Exception {
        Long type = confirmRecord.getBusinessType();
        Long detailId = confirmRecord.getPaymentDetailId();
        if(type == null || detailId == null) {
            throw new Exception("事务补偿失败,必要参数为空,type:"+type+",detailId:"+detailId);
        }
        BidPaymentsDetail detail = bidPaymentsDetailService.selectByPrimaryKey(detailId);
        BidPayments payments = bidPaymentsService.selectByPrimaryKey(detail.getPaymentId());
        if(payments == null) {
            throw new Exception("事务补偿失败,收款申请已不存在:"+detail.getPaymentId());
        }
        TrcTrack trcTrack = trcTrackProvider.selectByPrimaryKey(payments.getTrackId());
        if(trcTrack == null) {
            throw new Exception("事务补偿失败,商机信息已不存在:"+payments.getTrackId());
        }
        CstCustomer customer = cstCustomerProvider.selectByPrimaryKey(trcTrack.getCustomerId());
        if(customer == null) {
            throw new Exception("事务补偿失败,客户信息已不存在:"+trcTrack.getCustomerId());
        }
        final BidContract bidContract = bidContractService.getEffectContract(trcTrack.getId());
        try {
            if (0 == confirmRecord.getStatus()) {
                switch (type.intValue()) {
                    case 10:
                        bizBidPaymentProvider.receiveDeposit(trcTrack, customer,
                                detail.getReceiveType(), detail.getReceiveAmount(), userSession);
                        break;
                    case 20:
                        //首期款20%,不足额
                        bizBidPaymentProvider.receiveContractAmount(trcTrack, customer, detail.getReceiveType(),
                                detail.getReceiveAmount(), bidContract.getContractAmount(), false, false, userSession);
                        break;
                    case 21:
                        //首期款20%足额,新建合同号
                        bizBidPaymentProvider.receiveContractAmount(trcTrack, customer, detail.getReceiveType(),
                                detail.getReceiveAmount(), bidContract.getContractAmount(), true, true, userSession);
                        break;
                    case 22:
                        //首期款20%足额,但不是新建合同号
                        bizBidPaymentProvider.receiveContractAmount(trcTrack, customer, detail.getReceiveType(),
                                detail.getReceiveAmount(), bidContract.getContractAmount(), true, false, userSession);
                        break;
                    case 23:
                        //1、创建EBS客户
                        Map<String, String> resultMap = bidPaymentsDetailService.import_customer(
                                payments, userSession.getEbsBizId(), bidContract.getContractNo());
                        //2、定金转首期款
                        if (resultMap != null &&
                                !EbsWebServiceConstants.RETURN_STATUS_ERROR.equals(resultMap.get("status"))) {
                            bidPaymentsDetailService.intentionToDownpayment(payments, trcTrack.getId(),
                                    userSession.getEbsBizId(), bidContract.getContractNo());
                        }
                        break;
                    case 24:
                        //1、定金首期款
                        bidPaymentsDetailService.intentionToDownpayment(payments, trcTrack.getId(),
                                userSession.getEbsBizId(), bidContract.getContractNo());
                        break;
                    case 30:
                        //创建收款确认跟进记录
                        bidPaymentsDetailService.insertReceivedAmountAction(trcTrack, customer, detail, userSession);
                        break;
                }
                confirmRecord.setStatus(2);        //设置为已补偿
                bidPaymentDetailConfirmRecordMapper.updateByPrimaryKeySelective(confirmRecord);
            } else {
                LogUtil.error("无效的事务补偿,status状态为:" + confirmRecord.getStatus());
            }
        } catch (Exception e) {
            throw new Exception("事务补偿失败,"+e.getMessage());
        }
    }

调用rest接口,传事务记录ID,进行事务补偿

时间: 2024-10-11 00:09:10

分布式事务一致性,事务补偿实战的相关文章

分布式最终一致性事务

一.强一致性事务的瓶颈 在<分布式强一致性事务>一文中介绍了分布式事务的常用协议2PC二阶段提交,虽然2PC能在很大程度上实现分布式事务中各节点的ACID,但也存在同步阻塞问题,协调者单点故障,协调者因网络原因导致的通知不周或收不全参与者回复导致的异常等问题. 同时,即使能稳定的使用二阶段提交实现分布式事务,但是2PC通信过程中产生的耗时是巨大的,类似淘宝网,下完一个订单后可能需要与计费中心,订单中心,入库,出库等很多子系统打交道,此过程中带来的开销是不能接受的,等到所有流程通知响应完再返回告

聊聊分布式事务&amp;分布式系统事务一致性解决方案

事务就是一个会话过程中,对上下文的影响是一致的,要么所有的更改都做了,要么所有的更变都撤销掉.就要么生,要么死.没有半死不死的中间不可预期状态. 参考下薛定谔的猫. 事务是为了保障业务数据的完整性和准确性的. 分布式事务,常见的两个处理办法就是两段式提交和补偿. 两段式提交典型的就是XA,有个事务协调器,告诉大家,来都准备好提交,大家回复,都准备好了,然后协调器告诉大家,一起提交,大家都提交了. 补偿比较好理解,先处理业务,然后定时或者回调里,检查状态是不是一致的,如果不一致采用某个策略,强制状

分布式事务一致性方案

http://www.infoq.com/cn/articles/solution-of-distributed-system-transaction-consistency 在OLTP系统领域,我们在很多业务场景下都会面临事务一致性方面的需求,例如最经典的Bob给Smith转账的案例.传统的企业开发,系统往往是以单体应用形式存在的,也没有横跨多个数据库.我们通常只需借助开发平台中特有数据访问技术和框架(例如Spring.JDBC.ADO.NET),结合关系型数据库自带的事务管理机制来实现事务性

分布式事务之消息补偿解决方案

一.数据库本地事务 先看看数据库事务的定义:单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行 这个比较容易理解,操作过数据库的一般都懂,既是业务需求涉及到多个数据表操作的时候,需要用到事务 要么一起更新,要么一起不更新,不会出现只更新了部分数据表的情况,下边看看数据库事务的使用 1 begin tran 2 begin try 3 update Table1 set Field = 1 where ID = 1 4 update Table2 set Field = 2 whe

【原】JMS实现分布式事务一致性

前言:关于分布式事务话题一直是颇有争议的话题,在这里通过自己对消息中间件实现分布式事务做一个简单的demo,同时也让自己能在实践中可以获取经验和对分布式事务自己的一些思考. 1.本地事务 传统的ssh,ssm,ssi这些java框架在配置好事务管理之后,我们的应用就能保证事务一致性;例如 在同一个数据库中A给B转账100元并发送100代金券,在这个过程中,不管是服务器挂掉还是转账失败抛出异常,最终都能保证A的钱要么转出去成功B收到100元和代金券,或者A和B都没有发生变化  2.分布式事务 余额

明白了,原来分布式事务一致性可以这样搞

1.分布式事务问题的产生 何为事务? 所谓事务,大多数开发人员对事务并不陌生,它是由中间件提供的一种特有的机制.这种机制可以将一个活动所涉及的全部操作当做一个不可分割的执行单元,只有这个执行单元的所有操作均能正常执行的情况下才提交事物:否则,只要其中任一一个操作执行失败,都将导致整个执行单元回滚.现在的关系型数据库.部分消息中间件都具备这样的事务处理能力. 事务特性有哪些? Atomicity--原子性,是说事务中的所有操作的结果,要么全部成功,要么全部失败,不会存在中间状态.事务在执行过程中如

分布式事务一致性解决方案分析

一.从数据一致性谈起 一致性问题,"万恶之源"是数据冗余和分布并通过网络交互+网络异常是常态. 1.数据一致性的情形 主库.从库和缓存数据一致性,相同数据冗余,关系数据库,为保证关据库的高可用和高性能,一般会采用主从(备)架构并引入缓存.其中数据不一致性存在于数据冗余的时间窗口内.常用的解决方案见数据库之架构. 多副本数据之间的数据一致性,相同数据副本,大数据领域,一份数据会有多个副本并存储到不同的节点上.客户端可以访问任何一个节点进行读写操作.常用的解决方案是基于Paxos.ZAB.

分布式系统事务一致性解决方案

开篇 在OLTP系统领域,我们在很多业务场景下都会面临事务一致性方面的需求,例如最经典的Bob给Smith转账的案例.传统的企业开发,系统往往是以单体应用形式存在的,也没有横跨多个数据库.我们通常只需借助开发平台中特有数据访问技术和框架(例如Spring.JDBC.ADO.NET),结合关系型数据库自带的事务管理机制来实现事务性的需求.关系型数据库通常具有ACID特性:原子性(Atomicity).一致性(Consistency).隔离性(Isolation).持久性(Durability).

跨库事务一致性问题的解决方案(例)

我们看一个跨库事务一致性的问题,这是一个简单的场景:有新老两个系统,对应新老两套数据库,新数据库采用分库分表的设计,考虑到项目发布之后可能存在风险,采取了新老系统的并行方案.这个系统的业务比较简单:接收来自外部的数据,然后对数据进行核对处理.为了保证新老系统能够并行,在接收数据的时候必须实现双写方案,从而导致了跨库事务的一致性问题. 下面一幅图展示这一简单的场景 这里面会存在一个小问题,就是可能存在写入老库成功,但是写入新库失败的场景. 我们假设出现这种概率的情况是百万分之一,在系统发布的情况下

分布式系统事务一致性

单数据库一致性: 1. 利用事务 分布式系统事务一致性: 1. 本地事务消息队列:两段提交,利用本地事务保证消息的可靠性 生产者: 1). 在数据库(mysql)增加一个消息表,将本地数据修改和消息记录放到同一个事务中,保证同时成功或失败. 2). 本地数据修改成功后,事务提交完毕.producer向MQ发送一个消息,发送成功,更新消息表消息为已读 3). 为避免producer消息发送失败的情况.有一个定时任务,定时查询消息表,将未消费的消息放到MQ的消息队列中 消费者: 1). consum