美文网首页分布式架构
fescar源码分析3-RM

fescar源码分析3-RM

作者: leiwingqueen | 来源:发表于2019-02-05 00:08 被阅读11次

一、概要

这篇文章重点分析RM(resource manager)的源码。

  • RM 如何集成到业务进程
  • RM和TC的通讯过程(xid,branch id的传递和生成过程)

二、配置

我们摘取dubbo-account-service.xml的核心配置看看

<bean name="accountDataSource" class="com.alibaba.druid.pool.DruidDataSource"
          init-method="init" destroy-method="close">
        <property name="url" value="xxx"/>
        <property name="username" value="xxx"/>
        <property name="password" value="xxx"/>
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="initialSize" value="0" />
        <property name="maxActive" value="180" />
        <property name="minIdle" value="0" />
        <property name="maxWait" value="60000" />
        <property name="validationQuery" value="Select 'x' from DUAL" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        <property name="testWhileIdle" value="true" />
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        <property name="minEvictableIdleTimeMillis" value="25200000" />
        <property name="removeAbandoned" value="true" />
        <property name="removeAbandonedTimeout" value="1800" />
        <property name="logAbandoned" value="true" />
        <property name="filters" value="mergeStat" />
    </bean>

    <bean id="accountDataSourceProxy" class="com.alibaba.fescar.rm.datasource.DataSourceProxy">
        <constructor-arg ref="accountDataSource" />
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="accountDataSourceProxy" />
    </bean>

我们可以看到jdbcTemplate没有直接使用DruidDataSource作为数据源,而是使用了DataSourceProxy在外面封装了一层。我们可以猜到应该是在DataSourceProxy里针对RM的特性做了扩展。

三、源码分析

public class DataSourceProxy extends AbstractDataSourceProxy implements Resource {
@Override
    public ConnectionProxy getConnection() throws SQLException {
        assertManaged();
        Connection targetConnection = targetDataSource.getConnection();
        return new ConnectionProxy(this, targetConnection, targetDataSource.getDbType());
    }

可以看到这里返回的是RM使用代理模式实现的ConnectionProxy。
我们先看事务提交的操作。

public class ConnectionProxy extends AbstractConnectionProxy {
@Override
    public void commit() throws SQLException {
        if (context.inGlobalTransaction()) {
            try {
                register();
            } catch (TransactionException e) {
                recognizeLockKeyConflictException(e);
            }

            try {
                if (context.hasUndoLog()) {
                    UndoLogManager.flushUndoLogs(this);
                }
                targetConnection.commit();
            } catch (Throwable ex) {
                report(false);
                if (ex instanceof SQLException) {
                    throw (SQLException) ex;
                } else {
                    throw new SQLException(ex);
                }

            }
            report(true);
            context.reset();

        } else {
            targetConnection.commit();
        }
    }

这里有几个核心方法。

  1. register()
    请求TC注册分支事务。在这里会生成branch id。这里会涉及到锁冲突的问题。后面再抽时间分析这里加锁的策略
  2. UndoLogManager.flushUndoLogs(this);
    写回滚日志undo_log。注意这里的undo_log跟业务的事务是同一个事务,这也就是fescar博客提到的保证undo_log写入成功的依据。
  3. report(true);
    请求TC更新分支事务状态。

四、问题

  1. 锁的作用和锁的范围?
  2. xid的传递?在注册分支事务的时候xid是在哪一步保存下来的?
  3. register和report在TC的实现是如何?
  4. report超时或者失败分布式事务的后续处理如何?

带着这些问题接下来会继续去看源码分析。

相关文章

网友评论

    本文标题:fescar源码分析3-RM

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