`
dalan_123
  • 浏览: 86938 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

使用消息系统避免分布式事务

 
阅读更多
首先举个栗子:比如通过支付宝向余额宝转账1000元,这样一种生活中很平凡的事情,却可以引出很多问题:如果系统宕机挂掉,交易没有完成?那么数据就出现了不一致。等等类似的事情,在各类系统中都能找到类似情形。那么也可以换句专业的说法:当一个表update之后,如何保证另外一个与之关联的表也能完成update。

1、本地事务:

    支付宝账户表:A  id uid amount

    余额宝账户表:B  id uid amount

     用户id:uid = 100

   执行上面的过程分两部分:

    1、支付宝账户表-1000:update A set amount=amount - 1000 where uid = 100;

    2、余额宝账户表+1000:update B set amount=amount + 1000 where uid = 100;

如何保证两部分都能够完成,保证两部分“收支平衡”

对数据库熟悉的同学会那么我们使用transaction(事务)不就解决了

BEGIN TRANSACTION

   update A set amount=amount - 1000 where uid = 100;

    update B set amount=amount + 1000 where uid = 100;

END TRANSACTION

COMMIT;

OK,上面的操作是没有问题的

那么对spring熟悉的同学也知道 其实在spring只需要使用注解就OK了

@Transactional(rollbackFor=Exception.class)

public void updateAmount(){

   updateA();

   updateB();

}

是的,没有错的。能够完成。但是这些情况只是针对系统规模小,数据表在一个数据库实例上的;那么系统规模大,对应的数据表分布在不同的数据库实例上,分布在不同的物理节点上,前面采用的本地事务的方式就无用武之地了。

2、分布式事务(两阶段提交协议)

两阶段提交协议经常用来实现分布式事务;一般需要两个角色:协调器C和若干个事务执行者Si;那么事务执行者多半是具体的数据库,同时协调器和事务执行器可在一台机器上。

   1、应用程序application发起一个请求到TC(事务协调器)

   2、TC(事务协调器)将消息写到本地日志,再向所有的SI(事务执行者)的发送消息。

   3、Si(事务执行者)接受到消息之后,执行本地事务但是不commit,如果成功返回yes否则no;同样返回      之前仍要进行日志记录。

   4、Tc(事务协调器)接受到所有执行器返回的结果,如果所有的执行全部返回yes,那么发送commit消息给各个执行器,本地事务执行commit;若是有一个返回no,那么tc就会发送abort消息给各个执行器

注:tc和si把发送和接收到的消息存放到本地日志里,主要为了故障恢复复用,如若某一个si从故障中恢复后,先检查本地日志的内容,如果已接收到commit则本地事务执行器commit;若是abort,则回滚;

若是yes则在tc询问,确定下一步;若是什么都没有则可能前面执行已经崩溃,需要回滚。

熟悉java的同学可以看:http://acen-chen.iteye.com/blog/1055481
采用分布式事务,也满足了我们前面的需求,同时新的问题随之而来

      1、两阶段提交涉及多个节点的网络通信,通信时间如果过长

       2、事务的相对时间长了,那么锁定资源的时间也就长了

               那么在高并发的服务中,就会存在严重的性能问题。

3、消息队列

在高并发的环境中,我们一般会采用消息队列来避免分布式事务的执行

这和实际生活中,我们去饭店吃饭很类似,首先点单,这时服务员给你一张小票,等待服务器给你端上你的饭菜。

  在使用消息队列我们需要做到可靠凭证的保存(分布式事务的消息),有如下两种方式

   方式1、支付宝完成扣钱的动作时,并记录消息数据,消息数据和业务数据在同一个数据库实例

   BEGIN TRANSACTION

     update A set amount=amount - 1000 where uid = 100;
     INSERT INTO MESSAGE(UID,AMOUNT,STATUS) VALUES(1,1000,1)
   END TRANSACTION
   COMMIT;

那么我们可以将支付宝完成扣钱操作的消息通过及时服务发给余额宝,余额宝完成处理返回成功消息,支付宝收到消息,清除消息表中对应的消息记录,即完成本次扣钱操作。

   方式2、

     1)支付宝在扣款事务提交之前,向实时消息服务请求发送消息,实时消息服务只记录消       息数据,而不真正发送,只有消息发送成功后才会提交事务;

     2)当支付宝扣款事务被提交成功后,向实时消息服务确认发送。只有在得到确认发送指令后,实时消息服务才真正发送该消息;

    3)当支付宝扣款事务提交失败回滚后,向实时消息服务取消发送。在得到取消发送指令后,该消息将不会被发送;

    4)对于那些未确认的消息或者取消的消息,需要有一个消息状态确认系统定时去支付宝系统查询这个消息的状态并进行更新。为什么需要这一步骤,举个例子:假设在第2步支付宝扣款事务被成功提交后,系统挂了,此时消息状态并未被更新为“确认发送”,从而导致消息不能被发送。

优点:消息数据独立存储,降低业务系统与消息系统间的耦合;

缺点:一次消息发送需要两次请求;业务处理服务需要实现消息状态回查接口
------------------------------------------------------------------------------------------------------------------------------------
那么如上的消息队列也就解决了我们实际业务中的高并发情况下分布式事务处理性能低下的问题

在使用消息队列防止重复投递消息

解决方法很简单,增加消息应用状态表(message_apply),通俗来说就是个账本,用于记录消息的消费情况,每次来一个消息,在真正执行之前,先去消息应用状态表中查询一遍,如果找到说明是重复消息,丢弃即可,如果没找到才执行,同时插入到消息应用状态表(同一事务)。
for each msg in queue
  Begin transaction
    select count(*) as cnt from message_apply where msg_id=msg.msg_id;
    if cnt==0 then
      update B set amount=amount+10000 where userId=1;
      insert into message_apply(msg_id) values(msg.msg_id);
  End transaction
  commit;
分享到:
评论

相关推荐

    深入理解分布式事务

    分布式事务是指在分布式系统中,为了确保跨多个节点上的操作能够正确地完成或者全部回滚,所采取的一种事务处理机制。在这样的场景下,事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的...

    浅谈分布式事务实现技术及应用场景探讨.pdf

    4. 异步确保(Asynchronous Ensure):是一种基于消息队列的分布式事务实现技术。它可以确保事务的执行顺序和可靠性,避免了分布式事务中的竞争Condition。 5. 最大努力通知(Best-Effort Notification):是一种...

    分布式事务-可靠消息的服务的设计与实现(消息服务子系统)

    本文将深入探讨“分布式事务-可靠消息的服务的设计与实现”这一主题,主要围绕消息服务子系统,结合提供的资料,包括“微服务架构的分布式事务解决方案.pdf”、“rc_pay_dubbo_message.sql”数据库脚本、“龙果学院-...

    分布式事务.pdf

    除此之外,也有基于消息队列、补偿事务(TCC)等不同实现方式的分布式事务处理策略。 然而,在实际应用中,分布式事务的引入会增加系统的复杂度和开销,因此在决定是否采用分布式事务时,应该充分评估业务需求和...

    分布式事务详细介绍

    分布式事务是指在分布式系统中,为了保持事务的ACID(原子性、一致性、隔离性、持久性)特性,需要跨越多个资源管理器(如数据库、消息队列等)进行协调的一系列操作。在分布式系统中,事务的操作分布在不同的节点上...

    分布式事务专题-v1.1.pdf

    分布式事务的场景主要包括微服务架构中的远程调用、单体系统访问多个数据库实例以及多服务访问同一数据库实例但跨JVM进程。 CAP理论是分布式系统设计的基础理论之一,它涉及三个关键概念:一致性(Consistency)、...

    Atomikos实现分布式事务

    在Web项目中使用Atomikos实现分布式事务,通常包括以下步骤: 1. **集成Atomikos**:首先,你需要将Atomikos的依赖库添加到你的项目中,这可以通过Maven或Gradle的依赖管理来完成。确保引入的版本与你的项目所使用...

    记录redisson实现redis分布式事务锁

    本篇文章将详细探讨如何使用Redisson实现Redis分布式事务锁,以及在Spring Boot环境中如何进行集成。 首先,Redis作为一个内存数据库,其高速读写性能使其成为实现分布式锁的理想选择。分布式锁的主要作用是在多...

    Spring+JOTM 分布式事务管理

    使用Spring+JOTM的分布式事务,可以确保这两个操作要么全部成功,要么全部回滚,避免出现部分完成的事务状态。 总结来说,Spring+JOTM的组合为开发者提供了一个强大的工具,用于处理复杂的分布式事务场景。通过声明...

    多数据源分布式事务管理调研报告.docx

    【分布式事务概述】 分布式事务是指在分布式环境下,跨越多个数据源的操作...然而,需要注意的是,分布式事务的管理和实施会增加系统的复杂性,并可能导致性能下降,因此在设计系统时应权衡事务管理和性能之间的平衡。

    分布式事务解决方案1.pdf

    这两个操作通常会在不同的服务或数据库中进行,因此必须通过分布式事务机制确保它们要么同时成功,要么同时失败,以避免数据不一致的问题。 在分布式事务中,会出现多种异常情况,包括但不限于: 1. 数据库异常:...

    电商系统的分布式事务调优

    分布式事务在电商系统中的重要性不言而喻,特别是在微服务架构盛行的今天。当一个操作涉及多个服务或数据库时,传统的单库事务机制不足以保证数据的一致性。以文中提到的电商系统为例,玩家购买道具后,道具的更新与...

    分布式事务-幂等

    分布式事务-幂等 在分布式系统中,幂等性(Idempotence)是一个重要的概念,它确保了同一个操作无论执行多少次,结果始终相同。这一特性对于保证数据一致性、防止重复处理以及解决网络延迟等问题至关重要。尤其是在...

    微服务主题系统_分布式事务领域知识及常见解决方案

    例如,旅行预订系统需要确保机票、酒店和租车的预订同时成功,如果其中一个环节失败,其他环节也应回滚,这就需要使用分布式事务来保证整体操作的一致性。而系统间的同步超时和异步回调超时问题,可以通过超时重试、...

    大规模SOA服务分布式事务处理-程立.rar

    分布式事务是跨越多个独立资源(如数据库、消息队列等)的事务,它保证了在整个事务执行过程中的原子性、一致性、隔离性和持久性(ACID属性)。 接下来,我们来看分布式事务处理模型。最经典的模型之一是Saga模式,...

Global site tag (gtag.js) - Google Analytics