MySQL 數據庫的讀寫分離和負載均衡一般是通過第三方軟件來實現的。 也可以通過mysql驅動程序來實現,如com.mysql.jdbc.ReplicationDriver。
官網網址:
如下爲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=root
jdbc.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>