Mysql讀寫分離配置 + 代碼

一個簡單完整的 Mysql 主從複製,讀寫分離的示意圖。javascript

 


1. 首先搭建 Mysql 主從架構,實現 將 mater 數據自動複製到 slave java

 

MySQL 複製的工做方式很簡單,一臺服務器做爲主機,一臺或多臺服務器做爲從機。主機會把數據庫的變化記錄到日誌。一旦這些變化被記錄到日誌,就會馬上(或者以設定的時間間隔)被送到從機。mysql

 


使用MySQL 複製提供擴展大型網站的能力,這些大型網站的數據庫主要是讀操做(SELECTs)。從機用於複製主機的銷秏是不多的(一般每一個從機1%的開銷),在大型網站中每一個主機部署30 個從機也是常見的。sql

 

異步複製與同步複製數據庫

 

異步複製:MySQL自己支持單向的、異步的複製。異步複製意味着在把數據從一臺機器拷貝到另外一臺機器時有一個延時 – 最重要的是這意味着當應用系統的事務提交已經確認時數據並不能在同一時刻拷貝/應用到從機。一般這個延時是由網絡帶寬、資源可用性和系統負載決定的。然 而,使用正確的組件而且調優,複製能作到接近瞬時完成。服務器

 

同步複製:同步複製能夠定義爲數據在同一時刻被提交到一臺或多臺機器,一般這是經過衆所周知的「兩階段提交」作到的。雖然這確實給你在多系統中保持一致性,但也因爲增長了額外的消息交換而形成性能降低。網絡

 

使用MyISAM或者InnoDB存儲引擎的MySQL自己並不支持同步複製,然而有些技術,例如分佈式複製塊設備(簡稱DRBD),能夠在下層的 文件系統提供同步複製,容許第二個MySQL服務器在主服務器丟失的狀況下接管(使用第二服務器的複本)。要了解更多信息,請參 見:http://www.drbd.org/架構

 



 

 異步複製方案:app

 

1. Mysql 數據庫安裝異步

 

安裝過程省略: 詳細參見:http://pengranxiang.iteye.com/admin/blogs/1138059

 

服務器 Master :192.168.14.131

Mysql 安裝目錄: /home/mysql/mysql   (使用源碼安裝,獨立目錄)

 

服務器 Slave    :192.168.14.132

Mysql 安裝目錄 :/home/mysql/mysql

 

2. 修改配置

 

爲了避免影響原來的配置文件: /etc/my.cnf

 

建立新的配置文件,

 

cp /etc/my.cnf  /home/mysql/mysql/conf/master.cnf

 

cp /etc/my.cnf  /home/mysql/mysql/conf/slave.cnf

 

修改 master.cnf,  增長下面的設置 ,

(官方說明:爲了使用事務的InnoDB在複製中最大的持久性和一致性,你應該指定innodb_flush_log_at_trx_commit=1,sync_binlog=1選項。)

 

Cnf代碼

 收藏代碼

  1. log-bin=mysql-bin #slave會基於此log-bin來作replication  
  2. server-id=1           #master的標示  
  3.   
  4. innodb_flush_log_at_trx_commit=1  
  5.   
  6. sync_binlog=1  

 

 

修改 slave.cnf

 

Cnf代碼

 收藏代碼

  1. [mysqld]  
  2.   
  3. server-id=2 #slave的標示  

 

3. 啓動服務

 

Cnf代碼

 收藏代碼

  1. # Master  
  2.   
  3. # 若是 Mysql 已啓動,先關掉。  
  4.   
  5. /home/mysql/mysql/bin/mysqladmin -u root -p shutdown   
  6.   
  7. # 使用修改過的 master.cnf 啓動 mysql  
  8.   
  9. /home/mysql/mysql/bin/mysqld_safe --defaults-file=/home/mysql/mysql/conf/master.cnf &   

 

 

Java代碼

 收藏代碼

  1. # Slave  
  2.   
  3. # 若是 Mysql 已啓動,先關掉。  
  4.   
  5. /home/mysql/mysql/bin/mysqladmin -u root -p shutdown   
  6.   
  7. # 使用修改過的 slave.cnf 啓動 mysql  
  8.   
  9. /home/mysql/mysql/bin/mysqld_safe --defaults-file=/home/mysql/mysql/conf/slave.cnf &   

 

4. 在 Master 上建立一個專門用於複製的帳號 repl_user


5. 啓動主從複製功能

 

須要查看 Master 中的  Master status

 

mysql> show master status;

 

而後再 Slave 中,啓動複製

 


 

 

上面窗口是鏈接 Master , 下面窗口鏈接 Slave

 

6. 測試複製

 

在 Master 中插入一條數據, 而後在 Slave 中查詢。 能夠驗證。


2 簡單的讀寫分離實現

 

讀寫分離能夠直接在 客戶端 實現, 也能夠經過 代理服務器 實現。

 

代理服務器通常能夠選擇:

 

官方的:mysql proxy  地址:http://dev.mysql.com/downloads/mysql-proxy/#downloads

 

國產開源項目:amoeba

Amoeba開發者博客: http://amoeba.meidusa.com

Amoeba開源項目地址: http://www.sourceforge.net/projects/amoeba
amoeba 中文文檔下載地址:http://amoeba.meidusa.com/amoeba.pdf

 

這裏只演示最簡單的方案: JDBC 直接實現 讀寫分離。

package prx.dao;

import java.sql.Connection;
import java.sql.ResultSet;
import java.util.Properties;

import com.mysql.jdbc.ReplicationDriver;

public class Test {

	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"
		//
		// 經過 conn 的 readOnly 是否爲 true 來判斷,要取 connection 鏈接的數據庫是 主數據庫,仍是從數據庫
		// false 爲 主數據庫的鏈接
		// true 爲 從數據庫的鏈接
		
		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");

	}
}
相關文章
相關標籤/搜索