美文网首页
分布式事务

分布式事务

作者: 01010100 | 来源:发表于2020-06-28 23:09 被阅读0次

    1、线程安全
    保证线程安全一般分成两种方式:锁和原子变量
    原子变量:原子变量能够保证原子性的操作,意思是某个任务在执行过程中,要么全部成功,要么全部失败回滚,恢复到执行之前的初态,不存在初态和成功之间的中间状态。
    例如CAS操作,要么比较并交换成功,要么比较并交换失败。由CPU保证原子性。通过原子变量可以实现线程安全。一般会通过while/for循环来重新执行,直到赋值成功。
    在高度竞争的情况下,锁的性能将超过原子变量的性能,但是更真实的竞争情况下,原子变量的性能将超过锁的性能。

    2、disruptor
    https://tech.meituan.com/2016/11/18/disruptor.html

    分布式事务:
    刚性事务:
    2PC/3PC (XA)
    缺点:性能差、资源占用时间长、需要实现XA接口
    柔性事务:
    异步确保型
    缺点:侵入性高、实时性差
    纯补偿型
    缺点:侵入性高、开发成本高、一致性差
    TCC
    缺点“侵入性高、开发成本高
    最大努力通知
    缺点:侵入性高、开发成本高、实时性差

    Seata:
    Ali 微服务架构下的分布式事务

    XA:
    XA是一个分布式事务协议,由Tuxedo提出。
    XA中大致分为两部分:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如Oracle、DB2这些商业数据库都实现了XA接口,而事务管理器作为全局的调度者,负责各个本地资源的提交和回滚。
    即,XA是一个协议,一套接口

    2PC:
    两阶段提交协议(The two-phase commit protocol,2PC)是XA用于在全局事务中协调多个资源的机制。
    即,2PC 是一套XA用于实现分布式事务的机制,即具体实现方案。

    //假设有两个库,userDB, transactionDB

    //注册JDBC驱动
    Class.forName(JDBC_DRIVER);
    //打开连接
    userDbConn=DriverManager.getConnection(USER_DB_URL, USER, PASS);
    XAConnection xaUserConn = new MysqlXAConnection((com.mysql.jdbc.Connection), userDbConnn, logXaCommands);
    XAResource rmUser = xaUserConn.getXAResource();

    transDbConn=DriverManager.getConnection(TRANS_DB_URL, USER, PASS);
    XAConnection xaTransConn = new MysqlXAConnection((com.mysql.jdbc.Connection), transDbConnn, logXaCommands);
    XAResource rmTrans = xaTransConn.getXAResource();

    //AP 请求TM执行一个分布式事务 ,TM生成全局事务id
    byte[] gTRID="g12345".getBytes(); //全局事务id
    int formatId = 1;

    //分别执行 rmUser, rmTrans上的事务分支

    //TM 生成rmTrans上的事务分支id
    byte[] transid = "b00001".getBytes();
    Xid xid1 = new MysqlXid(gtrid, transid, formatId);
    //执行rmTrans上的事务分支
    rmTrans.start(xid1, XAResource.TMNOFLAGS);
    PreparedStateement insertSql = transDbConn.prepareStatement("insert int transTable ....");
    insertSql.executeUpdate();
    rmTrans.end(xid1, XAResource.TMSUCCESS);

    //TM生成rmUser上的事务分支
    byte[] user_id = "b00002".getBytes();
    Xid xid2 = new MysqlXid(gtrid, user_id, formatId);
    //执行userTrans上的事务分支
    rmUser.start(xid1, XAResource.TMNOFLAGS);
    PreparedStateement updateSql = userDbConn.prepareStatement("update Seller .....");
    updateSql.executeUpdate();
    rmUser.end(xid2, XAResource.TMSUCCESS);

    //两阶段提交
    //phase1:询问所有的RM准备提交事务分支
    int rmTrans_prepare = rmTrans.prepare(xid1);
    int rmUser_prepare = rmUser.prepare(xid2);

    //phase2:提交所有分支
    boolean onPhase = false; //T判断有2个事务分支看所以不能优化为一阶段提交

    if(rmTrans_prepare == XAResoure.XA_OK && rmUser_prepare == XAResource.XA_ok) {
    //所有事务分之 都prepare成功,提交所有事务分支
    rmTrans.commit(xid1, onephase);
    rmUser.commint(xid2, onePhase);
    } else {
    rmTrans.rollback(xid1);
    rmUser.rollback(xid2);
    }

    相关文章

      网友评论

          本文标题:分布式事务

          本文链接:https://www.haomeiwen.com/subject/rvzgfktx.html