mysql实现读写分离自带java驱动

来源:互联网 发布:java观察者模式实例 编辑:程序博客网 时间:2024/05/17 10:54

MySQL 数据库的读写分离和负载均衡一般是通过第三方软件来实现的。 也可以通过mysql驱动程序来实现,如com.mysql.jdbc.ReplicationDriver。
官网网址:
多主机连接配置
1.主备配置 2.负载连接配置 3.主从复制链接配置 4.高级负载和主备配置
如下为java实现读写分离demo

<dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <version>5.1.21</version>        </dependency>
package jdbc;import java.sql.Connection;import java.sql.ResultSet;import java.util.Properties;import com.mysql.jdbc.ReplicationDriver;public class MasterSlaveTest {    public static void main(String[] aa) throws Exception{          ReplicationDriver driver = new ReplicationDriver();          Properties props = new Properties();          //对slave自动重连          props.put("autoReconnect", "true");          //slaves 负载          props.put("roundRobinLoadBalance", "true");          //用户 密码          props.put("user", "root");          props.put("password", "abc123");          //jdbc:mysql:replication://master,slave1,slave2,slave3/test          Connection conn =driver.connect("jdbc:mysql:replication://192.168.0.109:3306,192.168.0.110:3306/test_db",props);          //master 进行读写          conn.setReadOnly(false);          conn.setAutoCommit(false);          conn.createStatement().executeUpdate("insert into tmp(a,b)values(11,22)");          conn.commit();          //slave 只读          conn.setReadOnly(true);          ResultSet rs = conn.createStatement().executeQuery("SELECT count(1) FROM tmp");          if(rs.next()){              System.out.println(rs.getInt(1));          }          rs.close();          conn.close();    }}

原理:使用mysql驱动自带的replicationDriver来实现,replicationDriver简单来说就是存在两个Connection,一个masterConnection,一个slaveConnection;当setReadonly(true)就把currentConnection=slaveConnection,反之设置为masterConnection
除此之外,ReplicationDriver还提供负载均衡,双master,下面我们通过代码演示。

<dependency>            <groupId>commons-dbcp</groupId>            <artifactId>commons-dbcp</artifactId>            <version>1.4</version>        </dependency>
package jdbc;import java.sql.Connection;import java.sql.ResultSet;import org.apache.commons.dbcp.BasicDataSource;public class LoadbalanceTest {    public static void main(String[] aa) throws Exception{        //数据库连接池        BasicDataSource ds = new BasicDataSource();         ds.setUrl("jdbc:mysql:loadbalance://192.168.0.109:3306,192.168.0.110:3306/test_db");        ds.setDriverClassName("com.mysql.jdbc.ReplicationDriver");        ds.setUsername("root");        ds.setPassword("abc123");        ds.setInitialSize(3); // 初始的连接数;        ds.setMaxActive(10);        ds.setMinIdle(3);        ds.setMaxIdle(5);        ds.setMaxWait(3000);        ds.setRemoveAbandoned(true);        ds.setRemoveAbandonedTimeout(2000);        for(int i=0;i<20;i++){            Connection connection = ds.getConnection();            connection.setReadOnly(true);//设置为只读,代理类将会获取Slave数据库连接,否则设置Master连接              ResultSet rs = connection.createStatement().executeQuery("SELECT count(1) FROM tmp");            if(rs.next()){                  System.out.println(rs.getInt(1));              }            rs.close();            connection.close();        }    }}

针对于replicationDriver spring和mybatis集成配置如下

使用ReplicationDriver而不是driver

jdbc.driverClassName=com.mysql.jdbc.ReplicationDriver

使用的是jdbc:mysql:replication://

jdbc.url=jdbc:mysql:replication://master:3306,slave1:3306,slave2:3306/test2?characterEncoding=utf8 jdbc.username=rootjdbc.password=123456

使用spring的事物,把读操作设置为readonly=true

 <!-- 配置dataSource -->  <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"id="dataSource"><property name="driverClassName" value="${jdbc.driverClassName}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/><property name="url" value="${jdbc.url}"></property>  </bean>   <!-- transaction configuration-->   <bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" />  </bean>   <!-- 定义事务通知 -->  <tx:advice id="txAdvice" transaction-manager="transactionManager">      <!-- 定义方法的过滤规则 -->      <tx:attributes>          <!-- 所有方法都使用事务 -->          <tx:method name="*" propagation="REQUIRED"/>          <!-- 定义所有get开头的方法都是只读的 -->          <tx:method name="get*" read-only="true"/>      </tx:attributes>  </tx:advice>  <!-- 定义AOP配置 -->  <aop:config>      <!-- 定义一个切入点 -->      <aop:pointcut expression="execution (* com.test.service.*.*(..))" id="services"/>      <!-- 对切入点和事务的通知,进行适配 -->      <aop:advisor advice-ref="txAdvice" pointcut-ref="services"/>  </aop:config>    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="configLocation" value="/WEB-INF/conf/mybatis-config.xml" />  </bean>