手把手教你实现一个Seata(secondDay TMimpl)

firstDay

参看上一篇

具体实现

  • 使用二阶段模式

  • 使用AOP代理数据源

  • 写一个Coordinator单独出来,使用RPC协议远程协调

  • HTTP拦截器传递全局事务上下文

完成上述的实现即可 包含的东西不少 有远程协议netty 还有spring 主要核心点在这两个大选手上面

2pc来实现

netty

首先需要一个网络通讯框架。因为只是内部AP TM RM使用所以不会使用http这种七层协议。Java端肯定首选netty这个框架

不会用netty的同学去学一下:

netty-guide

在基于阅读的同学已经学会netty的情况下

大体实现逻辑:定义一个netty-server netty-client 编解码实现类 具体的就不贴了 都是很容易实现的代码

tm-service

第一天写了如果需要使用2pc 则内部需包含TM(事务管理器) RM(资源管理) AP(application)

  • 使用AOP代理数据源

  • 1 需要使用到自定义数据库连接代理类(毕竟jdk自带的不满足自己的需求) 所以我们需要自定义一个实现Java的java.sql.Connection接口的实现类

    @Setter
    private boolean isFinished = true;

    @Override
    public void commit() throws SQLException {
        log.info("Connection:{} 进行提交操作",this);
        if(isFinished) {
            connection.commit();
        }
        if(!this.isClosed()){
            this.close();
        }
    }

    @Override
    public void rollback() throws SQLException {
        log.info("Connection:{} 进行回滚操作",this);
        if(isFinished) {
            connection.rollback();
        }
        if(!this.isClosed()){
            this.close();
        }
    }

    @Override
    public void close() throws SQLException {
        if(isFinished){
            log.info("无全局事务或全局事务处于完成完成状态,可以关闭数据库连接");
            log.info("Connection:{} 已关闭",this);
            connection.close();
        }else{
            log.info("全局事务存在且未完成,不关闭数据库连接");
            log.info("Connection:{} 未关闭",this);
        }
    }

    public ConnectionProxy(Connection connection) {
        super(connection);
    }

  • 2 需要一个切面用来替换掉原先的connect的东西


    /**
     * 代理数据源,替换得到的Connection为自定义的代理类
     */
    @Around("execution(* javax.sql.DataSource.getConnection(..))")
    public Connection around(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("数据库连接切面环绕切入前....");
        Connection connection = (Connection)joinPoint.proceed();
        ConnectionProxy myConnection = new ConnectionProxy(connection);
        if(GlobalTransactionManager.getGroupId() != null){
            log.info("发现全局事务,禁用自动提交");
            myConnection.setAutoCommit(false);
            myConnection.setFinished(false);
            //设置事务隔离级别为:读未提交
            myConnection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
            GlobalTransactionManager.addConnection(myConnection);
        }
        log.info("数据库连接切面环绕切入后....");
        return myConnection;
    }

你可能感兴趣的:(分布式)