`
gaozzsoft
  • 浏览: 427136 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

如何解决MySQL的master-slave模式中ReplicationDriver的使用问题

阅读更多
前言:
之前downpour有一个贴(http://www.iteye.com/topic/143714)讨论了在java中如何使用mysql的master-slave模式(master-slave模式的介绍见Qieqie的这个贴:http://www.iteye.com/topic/162717),其中readonly大大提到我们可以使用ReplicationDriver来从connection层把read或者write操作分开。这确实是一个比较好的方案,在那个帖子讨论后不久,我就在自己的机器上搭了一个mysql的master-slave模式,然后使用ReplicationDriver来控制读写访问不同的机器,测试通过了,事隔几个月之后,我准备把它用于生产环境中,但是问题来了,因为我的应用访问的数据库有多个,主要访问的库是master-slave模式,其他辅助库是就是指定的一台机器,这时候问题来了。

Mysql的文档是这么写的:ReplicationDriver does not currently work with java.sql.DriverManager -based connection creation unless it is the only MySQL JDBC driver registered with the DriverManager . DriverManager是一个单例模式,一个DriverManager只能注册一个ReplicationDriver驱动,也就是说ReplicationDriver和Driver两个类不能同时使用,郁闷,及其郁闷,由于我之前没有仔细看这段说明,所以没有预料到这种情况。摆在前面的路有几条

一,使用多个datasource解决问题,
二,所有得datasource都使用这个驱动,但是这样做有一个缺点,在文章后面我会详细阐述这种做法得缺点。
三,扩展再扩展,hack再hack。
四,这种方案是第二种方案的补充,详见后文。

首先,我们来看一下ReplicationDriver的官方使用教程:
Java代码
public static void main(String[] args) throws Exception {  
    ReplicationDriver driver = new ReplicationDriver();  
 
    Properties props = new Properties();  
 
    // We want this for failover on the slaves  
    props.put("autoReconnect", "true");  
 
    // We want to load balance between the slaves  
    props.put("roundRobinLoadBalance", "true");  
 
    props.put("user", "foo");  
    props.put("password", "bar");  
 
    //  
    // Looks like a normal MySQL JDBC url, with a  
    // comma-separated list of hosts, the first   
    // being the 'master', the rest being any number  
    // of slaves that the driver will load balance against  
    //  
 
    Connection conn =  
        driver.connect("jdbc:mysql://master,slave1,slave2,slave3/test",  
            props);  
 
    //  
    // Perform read/write work on the master  
    // by setting the read-only flag to "false"  
    //  
 
  //这个节点应该是通过spring的事务管理来设置,同时这个conn对象应该不是一个真正的connection,  
        //而是一个代理类,通过设置readonly,代理类会去使用不同的connection,  
        //那么问题是它该代理类使用的connection是哪里取的,抑或说难道它每次都会新开一个connection?,需要看源代码  
          
conn.setReadOnly(false);  
 
    conn.setAutoCommit(false);  
    conn.createStatement().executeUpdate("UPDATE some_table ....");  
    conn.commit();  
 
    //  
    // Now, do a query from a slave, the driver automatically picks one  
    // from the list  
    //  
 
    conn.setReadOnly(true);  
 
    ResultSet rs =   
      conn.createStatement().executeQuery("SELECT a,b FROM alt_table");  
 
     .......  
  } 

public static void main(String[] args) throws Exception {
    ReplicationDriver driver = new ReplicationDriver();

    Properties props = new Properties();

    // We want this for failover on the slaves
    props.put("autoReconnect", "true");

    // We want to load balance between the slaves
    props.put("roundRobinLoadBalance", "true");

    props.put("user", "foo");
    props.put("password", "bar");

    //
    // Looks like a normal MySQL JDBC url, with a
    // comma-separated list of hosts, the first
    // being the 'master', the rest being any number
    // of slaves that the driver will load balance against
    //

    Connection conn =
        driver.connect("jdbc:mysql://master,slave1,slave2,slave3/test",
            props);

    //
    // Perform read/write work on the master
    // by setting the read-only flag to "false"
    //

  //这个节点应该是通过spring的事务管理来设置,同时这个conn对象应该不是一个真正的connection,
    //而是一个代理类,通过设置readonly,代理类会去使用不同的connection,
    //那么问题是它该代理类使用的connection是哪里取的,抑或说难道它每次都会新开一个connection?,需要看源代码
   
conn.setReadOnly(false);

    conn.setAutoCommit(false);
    conn.createStatement().executeUpdate("UPDATE some_table ....");
    conn.commit();

    //
    // Now, do a query from a slave, the driver automatically picks one
    // from the list
    //

    conn.setReadOnly(true);

    ResultSet rs =
      conn.createStatement().executeQuery("SELECT a,b FROM alt_table");

     .......
  }
这个示例看上去非常之简单,我们可以很容易的就通过ReplicationDriver拿到了一个Connection,首先,对于我们来说,conn.setReadOnly对我们来说这个方法应该是通过spring的事务管理来设置,同时这个conn对象应该不是一个真正的connection,而是一个代理类,通过设置readonly,代理类会去使用不同的connection,那么问题是它该代理类使用的connection是哪里取的,抑或说难道它每次都会新开一个connection?,这就需要看源代码

那么现在我们要弄清楚ReplicationDriver是怎么回事,反编译之后我们看到:
Java代码
public ReplicationDriver() throws SQLException {  
    }  
 
    static {  
        try {  
            DriverManager.registerDriver(new NonRegisteringReplicationDriver());  
        } catch (SQLException E) {  
            throw new RuntimeException("Can't register driver!");  
        }  
    } 

public ReplicationDriver() throws SQLException {
}

static {
try {
DriverManager.registerDriver(new NonRegisteringReplicationDriver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}

看来看去,这个类中没有什么东西,那么再看看NonRegisteringReplicationDriver类吧。如下面的代码所示,这个类中主要就是这个方法connect方法

Java代码
public Connection connect(String url, Properties info) throws SQLException {  
        Properties parsedProps = parseURL(url, info);  
        if (parsedProps == null) {  
            return null;  
        }  
        Properties masterProps = (Properties) parsedProps.clone();  
        Properties slavesProps = (Properties) parsedProps.clone();  
        slavesProps.setProperty("com.mysql.jdbc.ReplicationConnection.isSlave",  
                "true");  
          
        String hostValues = parsedProps.getProperty("HOST");  
          
        if (hostValues != null) {  
            StringTokenizer st = new StringTokenizer(hostValues, ",");  
            StringBuffer masterHost = new StringBuffer();  
            StringBuffer slaveHosts = new StringBuffer();  
            if (st.hasMoreTokens()) {  
                String hostPortPair[] = parseHostPortPair(st.nextToken());  
                if (hostPortPair[0] != null) {  
                    masterHost.append(hostPortPair[0]);  
                }  
                if (hostPortPair[1] != null) {  
                    masterHost.append(":");  
                    masterHost.append(hostPortPair[1]);  
                }  
            }  
            boolean firstSlaveHost = true;  
            do {  
                if (!st.hasMoreTokens()) {  
                    break;  
                }  
                String hostPortPair[] = parseHostPortPair(st.nextToken());  
                if (!firstSlaveHost) {  
                    slaveHosts.append(",");  
                } else {  
                    firstSlaveHost = false;  
                }  
                if (hostPortPair[0] != null) {  
                    slaveHosts.append(hostPortPair[0]);  
                }  
                if (hostPortPair[1] != null) {  
                    slaveHosts.append(":");  
                    slaveHosts.append(hostPortPair[1]);  
                }  
            } while (true);  
            if (slaveHosts.length() == 0) {  
                throw SQLError  
                        .createSQLException(  
                                "Must specify at least one slave host to connect to for master/slave replication " 
                                        + "load-balancing functionality",  
                                "01S00");  
            }  
            masterProps.setProperty("HOST", masterHost.toString());  
            slavesProps.setProperty("HOST", slaveHosts.toString());  
        }  
        return new ReplicationConnection(masterProps, slavesProps);  
    } 

public Connection connect(String url, Properties info) throws SQLException {
Properties parsedProps = parseURL(url, info);
if (parsedProps == null) {
return null;
}
Properties masterProps = (Properties) parsedProps.clone();
Properties slavesProps = (Properties) parsedProps.clone();
slavesProps.setProperty("com.mysql.jdbc.ReplicationConnection.isSlave",
"true");

String hostValues = parsedProps.getProperty("HOST");

if (hostValues != null) {
StringTokenizer st = new StringTokenizer(hostValues, ",");
StringBuffer masterHost = new StringBuffer();
StringBuffer slaveHosts = new StringBuffer();
if (st.hasMoreTokens()) {
String hostPortPair[] = parseHostPortPair(st.nextToken());
if (hostPortPair[0] != null) {
masterHost.append(hostPortPair[0]);
}
if (hostPortPair[1] != null) {
masterHost.append(":");
masterHost.append(hostPortPair[1]);
}
}
boolean firstSlaveHost = true;
do {
if (!st.hasMoreTokens()) {
break;
}
String hostPortPair[] = parseHostPortPair(st.nextToken());
if (!firstSlaveHost) {
slaveHosts.append(",");
} else {
firstSlaveHost = false;
}
if (hostPortPair[0] != null) {
slaveHosts.append(hostPortPair[0]);
}
if (hostPortPair[1] != null) {
slaveHosts.append(":");
slaveHosts.append(hostPortPair[1]);
}
} while (true);
if (slaveHosts.length() == 0) {
throw SQLError
.createSQLException(
"Must specify at least one slave host to connect to for master/slave replication "
+ "load-balancing functionality",
"01S00");
}
masterProps.setProperty("HOST", masterHost.toString());
slavesProps.setProperty("HOST", slaveHosts.toString());
}
return new ReplicationConnection(masterProps, slavesProps);
}

上面这个方法也很简单,就是解析url后,然后访问确定master和slave机器一些properties的配置。越来越接近真相了,继续往下看,让我们掀起ReplicationConnection的头盖来:
先看构造方法:
Java代码
public ReplicationConnection(Properties masterProperties,  
            Properties slaveProperties) throws SQLException {  
        Driver driver = new Driver();  
          
        StringBuffer masterUrl = new StringBuffer("jdbc:mysql://");  
        StringBuffer slaveUrl = new StringBuffer("jdbc:mysql://");  
        String masterHost = masterProperties.getProperty("HOST");  
        if (masterHost != null) {  
            masterUrl.append(masterHost);  
        }  
        String slaveHost = slaveProperties.getProperty("HOST");  
        if (slaveHost != null) {  
            slaveUrl.append(slaveHost);  
        }  
        String masterDb = masterProperties.getProperty("DBNAME");  
        masterUrl.append("/");  
        if (masterDb != null) {  
            masterUrl.append(masterDb);  
        }  
        String slaveDb = slaveProperties.getProperty("DBNAME");  
        slaveUrl.append("/");  
        if (slaveDb != null) {  
            slaveUrl.append(slaveDb);  
        }  
 
//从这里可以看出,笔者前文提出的猜想是正确的,每一个ReplicationDriver其实是两个Connection的代理,这两个  
        //Connection才是真正访问DB的connection。        masterConnection = (com.mysql.jdbc.Connection) driver.connect(masterUrl  
                .toString(), masterProperties);  
        slavesConnection = (com.mysql.jdbc.Connection) driver.connect(slaveUrl  
                .toString(), slaveProperties);  
        currentConnection = masterConnection;  
    } 

public ReplicationConnection(Properties masterProperties,
Properties slaveProperties) throws SQLException {
Driver driver = new Driver();

StringBuffer masterUrl = new StringBuffer("jdbc:mysql://");
StringBuffer slaveUrl = new StringBuffer("jdbc:mysql://");
String masterHost = masterProperties.getProperty("HOST");
if (masterHost != null) {
masterUrl.append(masterHost);
}
String slaveHost = slaveProperties.getProperty("HOST");
if (slaveHost != null) {
slaveUrl.append(slaveHost);
}
String masterDb = masterProperties.getProperty("DBNAME");
masterUrl.append("/");
if (masterDb != null) {
masterUrl.append(masterDb);
}
String slaveDb = slaveProperties.getProperty("DBNAME");
slaveUrl.append("/");
if (slaveDb != null) {
slaveUrl.append(slaveDb);
}

//从这里可以看出,笔者前文提出的猜想是正确的,每一个ReplicationDriver其实是两个Connection的代理,这两个
//Connection才是真正访问DB的connection。 masterConnection = (com.mysql.jdbc.Connection) driver.connect(masterUrl
.toString(), masterProperties);
slavesConnection = (com.mysql.jdbc.Connection) driver.connect(slaveUrl
.toString(), slaveProperties);
currentConnection = masterConnection;
}

这个构造方法没有任何的玄机,从这里也可以看出,那么前文提出的猜想是正确的,每一个ReplicationDriver其实是两个Connection的代理,这两个Connection才是真正访问DB的connection。好了,看到这里看客们大概也看出来了,当调用connection.setReadonly的时候,其实就是把需要的masterConnection或者slavesConnection赋值给当前的currentConnection,ReplicationDriver就是这么个实现,原理也非常简单,那么怎么解决文章中开头提出的那个问题呢。

第一种方案:
改成多个datasource,这种方式是最简单,最粗鲁的,然后我们就可以看到一堆有一堆,一坨又一坨的datasource,然后你还有一堆堆一坨坨的JdbcTemplate,HibernateTemplate,SqlMapClientTemplate,等等。

第二种方案:
第二种方案是所有的驱动都是用ReplicationDriver,有同学问:那怎么行呢,因为我又的datasource不是master-slave模式的。还好,没有什么关系,即使是这样配置jdbc:mysql://192.168.1.1:3306,192.168.1.1:3306/xx也是没有关系的,带来的结果就是一个ReplicationDriver其实hold了两个connection,而这两个connection其实是连着同一个数据库。那么也就是说如果连接池里配置了50个connection,那么实际上却有100个connection连着数据库,这种事情还是比较让人郁闷的。


第三种方案:
看来看去,问题都出现在DriverManager上,如果我新建一个DriverManager,行否,于是新建一个类,名约ReplicationDriverManager。这样系统中就有两个DriverManager了,普通的DriverManager注册的驱动为Driver.java,ReplicationDriverManager注册的驱动为ReplicationDriver。大家互不干扰,貌似可行。粗略的看了一下代码,也是可以实现的,关键在于需要扩展连接池(至少c3p0是这样的,需要重写c3p0的两个类),然后还需要重写一个ReplicationDriver,将静态块中的DriverManager换成我们自己的DriverManager。然后还需要重写ReplicationConnection,Driver类等等,也是非常麻烦的。

想来想去,想破了头了,终于,还是有点头绪,就是在第二种方案的基础上,再次修改ReplicationConnection,也就是说,如果我的配置为jdbc:mysql://192.168.1.1:3306/xx,那么我强行把currentConnection设置为masterConnection,这样ReplicationConnection中的slavesConnection就一直是空着的,或者masterConnection和slavesConnection还有currentConnection这3个引用都指向同一个对象,那么连接池中配置50个连接,那么就是50个连接,不会变成100个连接了,而其他的master-slave模式的配置依旧,这个方式貌似看上去还是不错的。我们看看代码怎么写:
首先,来一个EasyReplicationDriver,代码如下:
Java代码
public class EasyReplicationDriver extends EasyNonRegisteringReplicationDriver  
        implements Driver {  
 
    public EasyReplicationDriver() throws SQLException {  
    }  
 
    static {  
        try {  
            DriverManager.registerDriver(new EasyNonRegisteringReplicationDriver());  
        } catch (SQLException E) {  
            throw new RuntimeException("Can't register driver!");  
        }  
    }  


public class EasyReplicationDriver extends EasyNonRegisteringReplicationDriver
implements Driver {

public EasyReplicationDriver() throws SQLException {
}

static {
try {
DriverManager.registerDriver(new EasyNonRegisteringReplicationDriver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
}

接着再来一个EasyNonRegisteringReplicationDriver,如下:
Java代码
/** 
* @author ahuaxuan(aaron zhang) 
* @since 2008-6-18 
* @version $Id$ 


*/ 
 
public class EasyNonRegisteringReplicationDriver extends NonRegisteringDriver {  
 
    public EasyNonRegisteringReplicationDriver() throws SQLException {  
    }  
 
    public Connection connect(String url, Properties info) throws SQLException {  
        Properties parsedProps = parseURL(url, info);  
        if (parsedProps == null) {  
            return null;  
        }  
        Properties masterProps = (Properties) parsedProps.clone();  
        Properties slavesProps = (Properties) parsedProps.clone();  
        slavesProps.setProperty("com.mysql.jdbc.ReplicationConnection.isSlave",  
                "true");  
          
        String hostValues = parsedProps.getProperty("HOST");  
          
        if (hostValues != null) {  
            StringTokenizer st = new StringTokenizer(hostValues, ",");  
            StringBuffer masterHost = new StringBuffer();  
            StringBuffer slaveHosts = new StringBuffer();  
            if (st.hasMoreTokens()) {  
                String hostPortPair[] = parseHostPortPair(st.nextToken());  
                if (hostPortPair[0] != null) {  
                    masterHost.append(hostPortPair[0]);  
                }  
                if (hostPortPair[1] != null) {  
                    masterHost.append(":");  
                    masterHost.append(hostPortPair[1]);  
                }  
            }  
            boolean firstSlaveHost = true;  
            do {  
                if (!st.hasMoreTokens()) {  
                    break;  
                }  
                String hostPortPair[] = parseHostPortPair(st.nextToken());  
                if (!firstSlaveHost) {  
                    slaveHosts.append(",");  
                } else {  
                    firstSlaveHost = false;  
                }  
                if (hostPortPair[0] != null) {  
                    slaveHosts.append(hostPortPair[0]);  
                }  
                if (hostPortPair[1] != null) {  
                    slaveHosts.append(":");  
                    slaveHosts.append(hostPortPair[1]);  
                }  
            } while (true);  
            /*if (slaveHosts.length() == 0) { 
                throw SQLError 
                        .createSQLException( 
                                "Must specify at least one slave host to connect to for master/slave replication " 
                                        + "load-balancing functionality", 
                                "01S00"); 
            }*/ 
            masterProps.setProperty("HOST", masterHost.toString());  
            slavesProps.setProperty("HOST", slaveHosts.toString());  
        }  
        return new EasyReplicationConnection(masterProps, slavesProps);  
    } 

/**
* @author ahuaxuan(aaron zhang)
* @since 2008-6-18
* @version $Id$


*/

public class EasyNonRegisteringReplicationDriver extends NonRegisteringDriver {

public EasyNonRegisteringReplicationDriver() throws SQLException {
}

public Connection connect(String url, Properties info) throws SQLException {
Properties parsedProps = parseURL(url, info);
if (parsedProps == null) {
return null;
}
Properties masterProps = (Properties) parsedProps.clone();
Properties slavesProps = (Properties) parsedProps.clone();
slavesProps.setProperty("com.mysql.jdbc.ReplicationConnection.isSlave",
"true");

String hostValues = parsedProps.getProperty("HOST");

if (hostValues != null) {
StringTokenizer st = new StringTokenizer(hostValues, ",");
StringBuffer masterHost = new StringBuffer();
StringBuffer slaveHosts = new StringBuffer();
if (st.hasMoreTokens()) {
String hostPortPair[] = parseHostPortPair(st.nextToken());
if (hostPortPair[0] != null) {
masterHost.append(hostPortPair[0]);
}
if (hostPortPair[1] != null) {
masterHost.append(":");
masterHost.append(hostPortPair[1]);
}
}
boolean firstSlaveHost = true;
do {
if (!st.hasMoreTokens()) {
break;
}
String hostPortPair[] = parseHostPortPair(st.nextToken());
if (!firstSlaveHost) {
slaveHosts.append(",");
} else {
firstSlaveHost = false;
}
if (hostPortPair[0] != null) {
slaveHosts.append(hostPortPair[0]);
}
if (hostPortPair[1] != null) {
slaveHosts.append(":");
slaveHosts.append(hostPortPair[1]);
}
} while (true);
/*if (slaveHosts.length() == 0) {
throw SQLError
.createSQLException(
"Must specify at least one slave host to connect to for master/slave replication "
+ "load-balancing functionality",
"01S00");
}*/
masterProps.setProperty("HOST", masterHost.toString());
slavesProps.setProperty("HOST", slaveHosts.toString());
}
return new EasyReplicationConnection(masterProps, slavesProps);
}
注意上面我注释掉的这段代码,如果我们想要ReplicationDriver支持jdbc:mysql://192.168.1.1:3306/xxx,那么就必须把上面那段代码注释掉。
第3步,让我们看看EasyReplicationConnection这个类:
Java代码
public EasyReplicationConnection(Properties masterProperties,  
            Properties slaveProperties) throws SQLException {  
        Driver driver = new Driver();  
          
        StringBuffer masterUrl = new StringBuffer("jdbc:mysql://");  
        StringBuffer slaveUrl = new StringBuffer("jdbc:mysql://");  
        String masterHost = masterProperties.getProperty("HOST");  
        if (masterHost != null) {  
            masterUrl.append(masterHost);  
        }  
        String slaveHost = slaveProperties.getProperty("HOST");  
        if (slaveHost != null) {  
            slaveUrl.append(slaveHost);  
        }  
        String masterDb = masterProperties.getProperty("DBNAME");  
        masterUrl.append("/");  
        if (masterDb != null) {  
            masterUrl.append(masterDb);  
        }  
        String slaveDb = slaveProperties.getProperty("DBNAME");  
        slaveUrl.append("/");  
        if (slaveDb != null) {  
            slaveUrl.append(slaveDb);  
        }  
          
        //从这里可以看出,笔者前文提出的猜想是正确的,每一个ReplicationDriver其实是两个Connection的代理,这两个  
        //Connection才是真正访问DB的connection。  
        masterConnection = (com.mysql.jdbc.Connection) driver.connect(masterUrl  
                .toString(), masterProperties);  
          
        if (slaveUrl.toString().contains("///")) {  
            if (logger.isDebugEnabled()) {  
                logger.debug(" ----- the salveUrl contains the '///', " +  
                        "that means there is no slaver, make slavesConnection = masterConnection --");  
            }  
            slavesConnection = masterConnection;  
        } else {  
            slavesConnection = (com.mysql.jdbc.Connection) driver.connect(slaveUrl  
                    .toString(), slaveProperties);  
        } 

public EasyReplicationConnection(Properties masterProperties,
Properties slaveProperties) throws SQLException {
Driver driver = new Driver();

StringBuffer masterUrl = new StringBuffer("jdbc:mysql://");
StringBuffer slaveUrl = new StringBuffer("jdbc:mysql://");
String masterHost = masterProperties.getProperty("HOST");
if (masterHost != null) {
masterUrl.append(masterHost);
}
String slaveHost = slaveProperties.getProperty("HOST");
if (slaveHost != null) {
slaveUrl.append(slaveHost);
}
String masterDb = masterProperties.getProperty("DBNAME");
masterUrl.append("/");
if (masterDb != null) {
masterUrl.append(masterDb);
}
String slaveDb = slaveProperties.getProperty("DBNAME");
slaveUrl.append("/");
if (slaveDb != null) {
slaveUrl.append(slaveDb);
}

//从这里可以看出,笔者前文提出的猜想是正确的,每一个ReplicationDriver其实是两个Connection的代理,这两个
//Connection才是真正访问DB的connection。
masterConnection = (com.mysql.jdbc.Connection) driver.connect(masterUrl
.toString(), masterProperties);

if (slaveUrl.toString().contains("///")) {
if (logger.isDebugEnabled()) {
logger.debug(" ----- the salveUrl contains the '///', " +
"that means there is no slaver, make slavesConnection = masterConnection --");
}
slavesConnection = masterConnection;
} else {
slavesConnection = (com.mysql.jdbc.Connection) driver.connect(slaveUrl
.toString(), slaveProperties);
}
主要就是加了一个判断,一旦路径中出现///,那么就证明没有slave机器,那么就可以把masterConnection赋值给slavesConnection了。这样一来就ok了。

经过3个类的改写之后,终于,我们可以使用ReplicationDriver的功能了,看来看去还是这种方式最美好。

不过由于ahuaxuan的水平所限,可能在以上的方案中有其没有发现的问题,抑或有更好的方案,希望大家不吝赐教。
分享到:
评论

相关推荐

    数据库-Mongodb的master-slave模式与master-master模式实验.rar

    在分布式系统中,为了确保数据的高可用性和容错性,MongoDB提供了两种复制模式:master-slave(主从模式)和master-master(主主模式)。本实验将深入探讨这两种模式的工作原理、设置方法以及它们在实际应用中的优...

    Modbus-Master-Slave-for-Arduino-master.zip_Master/Slave_arduino

    标题中的"Modbus-Master-Slave-for-Arduino-master.zip_Master/Slave_arduino"指出这是一个关于Arduino平台的Modbus主从通信库。Modbus是一种广泛使用的工业通信协议,允许不同设备之间交换数据,尤其在自动化系统中...

    sharding-master-slave

    在`sharding-master-slave`项目中,我们将看到如何将`Sharding-JDBC`与`SpringBoot`相结合,以实现数据的高效管理和访问。 1. **分库分表策略** `Sharding-JDBC`支持自定义分片策略,这在`描述`中提到。通常,分片...

    36 为多线程们安排一位经理—Master-Slave模式详解.pdf

    在Java并发编程中,Master-Slave模式是一种常见的多线程处理策略,它借鉴了“分而治之”的思想,将一个大任务分解为多个小任务,分配给多个工作线程(Slave)执行,由一个主控线程(Master)协调管理。这种模式在...

    activemq_master-slave集群安装文档

    ActiveMQ Master-Slave集群是一种高可用性和容错性的解决方案,确保即使主节点(Master Broker)发生故障,消息也不会丢失,因为它们已经被复制到从节点(Slave Broker)。这种配置是ActiveMQ推荐的策略之一,提供了...

    Mysql-master-slave.rar_Master/Slave_slave mysql

    5. **启动复制**:在从服务器上,使用`START SLAVE`命令启动复制进程。此时,从服务器将开始读取主服务器的binlog并执行相应的SQL语句。 二、主从复制工作原理 1. **写操作**:在主服务器上,任何数据修改都会被...

    activemq-master-slave集群安装文档.doc

    在JDBC Master Slave模式中,Master Broker和Slave Broker都尝试获取数据库的锁,成功获取的Broker将成为Master,而未能获取的则作为Slave。这种配置通常要求Master和Slave部署在不同的服务器上,以提高容错能力。在...

    Master-Slave 的应用一

    在企业级开发中,主从关系(Master-Slave)是一种常见的架构模式,广泛应用于数据库复制、分布式系统、任务调度等多个领域。这种模式的核心在于,一个主节点(Master)负责处理请求、执行关键操作或决策制定,而一个...

    mysql master/slave介绍及配置

    Master-Slave的数据库机构解决了很多问题,特别是read/write比较高的web2.0应用: 1、写操作全部在Master结点执行,并由Slave数据库结点定时(默认60s)读取Master的bin-log 2、将众多的用户读请求分散到更多的...

    第1步 master-slave1和slave2配置网络和搭建Hadoop集群环境.docx

    第1步 master-slave1和slave2配置网络和搭建Hadoop集群环境.docx

    搭建MySQL的MasterSlave架构

    MySQL的Master-Slave架构是一种常见的数据库高可用性和负载均衡解决方案。它允许数据从一个主服务器(Master)实时同步到一个或多个从服务器(Slave)。在这种架构中,所有的写操作都在主服务器上执行,而从服务器则...

    docker-mysql-master-slave-master.zip

    此资源为shardingsphere 调研...内容:一个master mysql docker实例,一个slave docker实例 内置3个库,mydb,mydb0,mydb1。仅开启了这三个库的主从。如果三个库主从不够用,自行配置。 使用:1.解压 2.执行build.sh

    Master-_-Slave-Core

    "Master-_-Slave-Core"标题暗示了这是一个关于I2C主从核心的项目,其中包含了一套用于实现I2C主从模式的代码。 I2C协议是由飞利浦(现NXP半导体)在1980年代初设计的,它允许在一个总线上连接多个设备,减少了所需...

    Modbus-Master-Slave-for-Arduino-master_fierce2gz_arduinomodbus_M

    1. **安装库**:首先,需要将解压后的"Modbus-Master-Slave-for-Arduino-master"文件夹放入Arduino IDE的库文件夹中,重启IDE后,即可在“Sketch”->"Include Library"菜单中看到Modbus的相关选项。 2. **配置主...

    activemq master-slave搭建的NFSV4文档

    3. **主从配置**:在主节点的 `activemq.xml` 中配置 master-slave 组件,包括 slave URL 和其他相关参数。同时,确保 slave 节点的配置文件指向主节点。 ### 启动与验证 1. **启动 MQ**:先启动 master,然后启动...

    FreeModbus_Slave-Master-RTT-STM32-master_stm32mastermodbus_stm32

    《FreeModbus_Slave-Master-RTT-STM32-master_stm32mastermodbus_stm32:深入理解MODBUS通信在STM32中的应用》 MODBUS通信协议,作为工业自动化领域的标准通信协议,因其简单、开放、易实现的特点,在嵌入式系统...

    基于MySQL数据库复制Master-Slave架构的分析

    MySQL数据库复制Master-Slave架构是一种常见的数据库高可用性和扩展性的解决方案。在这一架构中,数据库被分为一个主服务器(Master)和一个或多个从服务器(Slave)。主服务器接收并处理所有的写操作,如INSERT、...

    mysql-master-master

    MySQL的主主复制(Master-Master Replication)是一种高可用性解决方案,它允许两个或多个数据库服务器互相复制数据,形成一个集群。在这种模式下,每个节点既是主节点,也是从节点,可以接受读写操作。当一个节点...

    Master-slave-alarm-system.zip_Master/Slave_上位机报警

    "Master-slave-alarm-system"是一个基于主从模式的分布式系统,由主设备(Master)和多个从设备(Slave)组成。主设备负责协调和监控所有从设备,而从设备则负责采集温度数据并向主设备报告。这种架构允许系统扩展至...

Global site tag (gtag.js) - Google Analytics