在CentOS7上搭建MySQL主從複製與讀寫分離

MySQL主從複製原理

MySQL的主從複製和MySQL的讀寫分離二者有着緊密聯繫,首先要部署主從複製,只有主從複製完成了,才能在此基礎上進行數據的讀寫分離。前端

(1)MySQL支持複製的類型。java

1)基於語句的複製。MySQL默認採用基於語句的複製,效率比較高。mysql

2)基於行的複製。把改變的內容複製過去,而不是把命令在從服務器上執行一遍。linux

3)混合類型的複製。默認採用基於語句的複製,一旦發現基於語句沒法精確複製時,就會採用基於行的複製。sql

(2)MySQL複製的工做過程如圖所示。
在CentOS7上搭建MySQL主從複製與讀寫分離
1)在每一個事務更新數據完成以前,Master在二進制日誌記錄這些改變。寫入二進制日誌完成後,Master通知存儲引擎提交事務。數據庫

2)Slave將Master的Binary log複製到其中繼日誌。首先,Slave開始一個工做線程——I/O線程,I/O線程在Master上打開一個普通的連接,而後開始Binlog dump process。Binlog dump process從Master的二進制日誌中讀取事件,若是已經跟上Master,它會睡眠並等待Master產生新的事件。I/O線程將這些事件寫入中繼日誌。vim

3)SQL slave thred(SQL從線程)處理該過程的最後一步。SQL線程從中繼日誌讀取事件,並重放其中的事件而更新Slave的數據,使其與Master中的數據一致。只要該線程與I/O線程保持一致,中繼日誌一般會位於OS的緩存中,因此中繼日誌的開銷很小。後端

複製過程當中有一個很重要的限制,即複製在Slave上是串行化的,也就是說Master上的並行更新操做不能在Slave上並行操做。緩存

MySQL讀寫分離原理

簡單來講,讀寫分離(見圖所示)就是隻在主服務器上寫,只在從服務器上讀。基本原理是讓主數據庫處理事務性查詢,而從數據庫處理select查詢。數據庫複製被用來把事務性查詢致使的變動同步到羣集中的從數據庫。
在CentOS7上搭建MySQL主從複製與讀寫分離
基於中間代理層實現:代理通常位於客戶端和服務器之間,代理服務器接到客戶端請求經過判斷後轉發到後端數據庫。tomcat

實驗環境

使用五臺服務器模擬搭建,具體的拓撲如圖所示:
在CentOS7上搭建MySQL主從複製與讀寫分離

實驗環境表:
在CentOS7上搭建MySQL主從複製與讀寫分離
實施步驟

1.搭建MySQL主從複製。

(1)創建時間同步環境,在主節點上搭建時間同步服務器。

1)安裝NTP。

[root@localhost ~]# yum install ntp -y

2)配置NTP。

[root@localhost ~]# vim /etc/ntp.conf 
server 127.127.126.0                    //本地是時鐘源//
fudge 127.127.126.0 stratum 8          //設置時間層級爲8(限制在15內)//

3)重啓服務。

[root@localhost ~]# systemctl restart ntpd.service

(2)在從節點服務器上進行時間同步。

[root@localhost ~]# yum install ntpdate -y
[root@localhost ~]# /usr/sbin/ntpdate 192.168.126.138  //同步主服務器的時間//

(3)在每臺服務器上關閉firewalld防火牆。

[root@localhost ~]# systemctl stop firewalld.service   //關閉防火牆//
[root@localhost ~]# setenforce 0

(4)安裝MySQL數據庫。在Master、Slave一、Slave2上安裝,我用的數據庫是MySQL5.7.17這裏安裝完畢再也不演示。

(5)配置MySQL Master主服務器。

1)在/etc/my.cnf中修改或者增長如下內容。

[root@localhost mysql]# vim /etc/my.cnf
server-id = 11
log-bin=master-bin             //主服務器日誌文件//
log-slave-updates=true      //從服務器更新二進制日誌//

2)重啓MySQL服務。

[root@localhost ~]# systemctl restart mysqld.service

3)登陸MySQL程序,給服務器受權。

[root@localhost ~]# mysql -uroot -p
mysql> GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.126.%' IDENTIFIED BY '123456';      //受權//
mysql> FLUSH PRIVILEGES;
mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000001 |      604 |              |                  |                   |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
其中File列顯示日誌名,position列顯示偏移量。

(6)配置從服務器。
1)在/etc/my.cnf中修改或者增長如下內容。

[root@localhost ~]# vim /etc/my.cnf
server-id = 22
relay-log=relay-log-bin             //從主服務器上同步日誌文件記錄到本地//
relay-log-index=slave-relay-bin.index   //定義relay-log的位置和名稱//

這裏要注意server-id不能與主服務器相同。

2)重啓mysql服務。

[root@localhost ~]# systemctl restart mysqld.service

3)登陸mysql,配置同步。

按主服務器結果更改下面命令中的master_log_file和master_log_pos的參數。

[root@localhost ~]# mysql -u root -p
mysql> change master to master_host='192.168.126.138',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=604;

4)啓動同步。

mysql> start slave;

5)查看Slave狀態,確保如下兩個值爲YES。

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.126.138
                  Master_User: myslave
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000001
          Read_Master_Log_Pos: 604
               Relay_Log_File: relay-log-bin.000002
                Relay_Log_Pos: 321
        Relay_Master_Log_File: master-bin.000001
             Slave_IO_Running: Yes           
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB:

(7)驗證主從複製效果。

1)在主服務器上新建數據庫 db_test。

mysql>  create database db_test;

2)在主、從服務器上分別查看數據庫,顯示數據庫相同,則主從複製成功。

mysql> show databases;      //主服務器//
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db_test            |
| mysql              |
| performance_schema |
| school             |
| sys                |
+--------------------+
6 rows in set (0.03 sec)

mysql> show databases;    //從服務器//
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db_test            |
| kgc                |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
6 rows in set (0.05 sec)

搭建MySQL讀寫分離

Amoeba(變形蟲),這個軟件致力於MySQL的分佈式數據庫前端代理層,它主要爲應用層訪問MySQL時充當SQL路由,並具備負載均衡、高可用性、SQL過濾、讀寫分離、可路由相關到目標數據庫、可併發請求多臺數據庫。經過Amoeba可以完成多數據源的高可用、負載均衡、數據切片的功能。

(1)在主機Amoeba上安裝Java環境。

Amoeba是基於jdk1.5開發的,因此官方推薦使用jdk1.5或1.6版本,高版本不建議使用。

[root@localhost ~]# systemctl stop firewalld.service 
[root@localhost ~]# setenforce 0
[root@localhost tomcat]# cp jdk-6u14-linux-x64.bin /usr/local/
[root@localhost local]# ./jdk-6u14-linux-x64.bin    //根據提示按Enter鍵完成便可//
[root@localhost local]# mv jdk1.6.0_14/ /usr/local/jdk1.6
[root@localhost local]# vim /etc/profile

增長如下配置

export JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$AMOEBA_HOME/bin

[root@localhost local]# source /etc/profile   //啓動//

Java環境已配置成功。

(2)安裝並配置Amoeba軟件

[root@localhost local]# mkdir /usr/local/amoeba  建立工做路徑//
[root@localhost tomcat]# tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba   //解壓安裝包//
[root@localhost tomcat]# chmod -R 755 /usr/local/amoeba/  //提示amoeba權限//
[root@localhost tomcat]# /usr/local/amoeba/bin/amoeba
amoeba start|stop   //顯示此內容說明Amoeba安裝成功//

(3)配置Amoeba讀寫分離,兩個Slave讀負載均衡。
1)Master、Slave一、Slave2中開放權限給Amoeba訪問。

grant all on *.* to test@'192.168.126.%' identified by '123.com';

2)編輯amoeba.xml配置文件。

[root@localhost tomcat]# cd /usr/local/amoeba/
[root@localhost amoeba]# vim conf/amoeba.xml 
---30行--

 <property name="user">amoeba</property>
----32行---------
 <property name="password">123456</property>

---117-去掉註釋-
 <property name="defaultPool">master</property>
 <property name="writePool">master</property>
 <property name="readPool">slaves</property>

3)編輯dbServers.xml配置文件。

vi conf/dbServers.xml

--26-29--去掉註釋--      //行//
 <property name="user">test</property>    

 <property name="password">123.com</property>

-----42-主服務器地址---
<dbServer name="master"  parent="abstractServer">
 <property name="ipAddress">192.168.126.138</property>
--52-從服務器主機名-
<dbServer name="slave1"  parent="abstractServer">
--55-從服務器地址-
 <property name="ipAddress">192.168.126.162</property>
 從服務器slave2      
<dbServer name="slave2"  parent="abstractServer">      //添加//
 <property name="ipAddress">192.168.126.232</property>
 <dbServer name="slaves" virtual="true">
 <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">

--末尾--
<property name="poolNames">slave1,slave2</property>    //修改//
 </poolConfig>

4)配置無誤後,可用啓動Amoeba軟件,其默認端口爲TCP 8066。

[root@localhost amoeba]# /usr/local/amoeba/bin/amoeba start&
[root@localhost amoeba]#  netstat -anpt | grep java
tcp6       0      0 127.0.0.1:28750         :::*                    LISTEN      3370/java           
tcp6       0      0 :::8066                 :::*                    LISTEN      3370/java 
.....//省略//

(4) 測試
1)在client主機上。

[root@localhost ~]# yum install mysql -y

能夠經過代理訪問MySQL:

[root@localhost ~]# mysql -u amoeba -p123456 -h 192.168.126.132 -P8066
..... //省略//
MySQL [(none)]>

2)在Master上建立一個表,同步到各從服務器上,而後關閉各從服務器的Slave功能,再插入區別語句。

mysql> use db_test;
Database changed
mysql> create table zang (id int(10),name varchar(10),address varchar(20)); //建立表//
Query OK, 0 rows affected (0.06 sec)

分別在兩臺服務器上關閉slave功能:

mysql> stop slave;

而後在主服務器上插入區別語句:

mysql> insert into zang values('1','zhang','this_is_master');  //插入數據//

3)從服務器上手動插入其餘內容。

slave1:
mysql> use db_test;
mysql> insert into zang values('2','zhang','this_is_slave1');   //插入數據//
Query OK, 1 row affected (0.03 sec)

slave2:
mysql> use db_test;
mysql> insert into zang values('3','zhang','this_is_slave2'); //插入數據//
Query OK, 1 row affected (0.03 sec)

4)測試讀操做
在client主機上第一次查詢的結果以下:

MySQL [db_test]> select * from zang;
+------+-------+----------------+
| id   | name  | address        |
+------+-------+----------------+
|    3 | zhang | this_is_slave2 |
+------+-------+----------------+
1 row in set (0.01 sec)

第二次查詢的結果以下:

MySQL [db_test]> select * from zang;
+------+-------+----------------+
| id   | name  | address        |
+------+-------+----------------+
|    2 | zhang | this_is_slave1 |
+------+-------+----------------+
1 row in set (0.01 sec)

第三次查詢結果:

MySQL [db_test]> select * from zang;
+------+-------+----------------+
| id   | name  | address        |
+------+-------+----------------+
|    3 | zhang | this_is_slave2 |
+------+-------+----------------+
1 row in set (0.01 sec)

5)測試寫操做。
在client主機上插入一條語句:

MySQL [db_test]> insert into zang values('5','zhang','write_test');
Query OK, 1 row affected (0.02 sec)

但在client上查詢不到,最終只有在Master上才能查看到這條語句內容,說明寫的操做在Master服務器上。

mysql> select * from zang;
+------+-------+----------------+
| id   | name  | address        |
+------+-------+----------------+
|    1 | zhang | this_is_master |
|    5 | zhang | write_test     |
+------+-------+----------------+
2 rows in set (0.01 sec)

由此驗證,已經實現了MySQL讀寫分離,目前全部的寫操做所有在Master主服務器上,用來避免數據 的不一樣步;全部的讀操做都分攤給了Slave從服務器,用來分擔數據庫的壓力。

相關文章
相關標籤/搜索