MySQL 主從複製與讀寫分離

         在實際生產環境中,若是對數據庫的讀寫都在同一塊數據庫服務器中操做,不管是在安全性、高可用性,仍是高併發等各個方面都是徹底不能知足實際需求的,所以,通常都是經過主從複製(Master- Slave) 的方式來同步數據,再經過讀取分離來提高數據庫的併發負載能力。java


    MySQL 主從複製原理mysql

MySQL 的主從複製和MySQL 的讀寫分離二者有着緊密關係,首先要部署主從複製,只有主從複製完成,才能在此基礎上進行讀寫分離linux

         MySQL 支持的複製類型c++

1)基於語句的複製。在主服務器上執行的 SQL 語句,在從服務器上執行一樣的語句。MySQL 默認採用基於語句的複製,效率較高。sql

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

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


MySQL 讀寫分離原理後端

        讀寫分離就是基於主服務器上寫,只在從服務器上讀。基本原理是讓數據庫處理事務性查詢,而從數據庫處理 select 查詢。數據庫被複制用來把事務性致使的變動同步到羣集中的數據庫。centos

        基於中間代理從實現,代理通常位於客戶端和服務器之間,代理服務器接到客戶端請求經過判斷後轉發到後端數據庫。安全


實驗環境

本案例使用五臺服務器模擬搭建,具體拓撲圖以下:

1


主機                   操做系統                      IP地址                            主要軟件

Master             Centos 7  x86_64           192.168.213.170         mysql-5.5.24.tar.gz

Slave 1              Centos 7  x86_64           192.168.213.168        mysql-5.5.24.tar.gz

Slave 2              Centos 7  x86_64           192.168.213.171        mysql-5.5.24.tar.gz

Amoeba           Centos 7  x86_64            192.168.213.166        jdk-6u14-linux-x64.bin

                                                                                                             amoeba-mysql-binary-2.2.0.tar.gz

客戶端                  Centos 7  x86_64           192.168.213.172

因此須要的軟件包可經過此連接到百度雲盤下載:

連接:https://pan.baidu.com/s/1Wv65-ZmAIasN3EPAzB8J7Q 密碼:5q4b


搭建MySQL 主從複製

一. 創建時間同步,在主節點上搭建時間同步服務器。

檢查是否安裝 NTP.

[root@master ~]# rpm -q ntp
ntp-4.2.6p5-25.el7.centos.2.x86_64

配置 NTP  (在末行插入)

[root@master ~]# vim /etc/ntp.conf

server 127.127.213.0                                      //本地是時鐘源
fudge 127.127.100.0 stratum 8                    //設置時間層級爲8

啓動 NTP ,關閉防火牆和安全性加強功能

[root@master ~]#service ntpd start
Redirecting to /bin/systemctl start ntpd.service
[root@master ~]#systemctl stop firewalld.service
[root@master ~]#setenforce 0

二.  在從節點服務器上進行時間同步 (節點服務器 slave01  和 slave02  配置相同)

檢查是否安裝 NTP.

[root@slave01 ~]# rpm -q ntp
ntp-4.2.6p5-25.el7.centos.2.x86_64

啓動 NTP ,關閉防火牆和安全性加強功能

[root@slave01 ~]# service ntpd start
Redirecting to /bin/systemctl start ntpd.service
[root@slave01 ~]#  systemctl stop firewalld.service
[root@slave01 ~]# setenforce 0

與主服務器進行時間同步

[root@slave01 ~]# /usr/sbin/ntpdate 192.168.213.170                             //與主服務器進行時間同步
  7 Sep 10:10:30 ntpdate[4940]: the NTP socket is in use, exiting

三.   安裝 MySQL 數據庫,三個服務 器 master 、 slave01 、slave 02  都要安裝

安裝編譯環境

yum install gcc gcc-c++ make cmake ncurses-devel bison libaio-devel –y

添加 mysql 用戶並加入 mysql  組

[root@master LNMP]# useradd  -s /sbin/nologin mysql            //建立 mysql 用戶                 
[root@master LNMP]# mkdir /usr/local/mysql                           //建立 mysql 目錄

解壓 MySQL 軟件包,配置安裝mysql

[root@master LNMP]# tar zxvf mysql-5.5.24.tar.gz -C /opt/

[root@master mysql-5.5.24]# cmake  \
> -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \                   //mysql  軟件安裝位置
> -DDEFAULT_CHARSET=utf8 \                                                     //默認字符集
> -DDEFAULT_COLLATION=utf8_general_ci \                            //默認字符校驗
> -DWITH_EXTRA_CHARSETS=all \                                               //額外的編碼,請使用 all
> -DSYSCONFDIR=/etc \
> -DMYSQL_DATADIR=/home/mysql/ \
> -DMYSQL_UNIX_ADDR=/home/mysql/mysql.sock \
> -DWITH_MYISAM_STORAGE_ENGINE=1 \                                 //存儲引擎
> -DWITH_INNOBASE_STORAGE_ENGINE=1 \
> -DWITH_ARCHIVE_STORAGE_ENGINE=1 \
> -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
> -DENABLED_LOCAL_INFILE=1 \                                                     //啓用本地加載數據
> -DWITH_SSL=system \
> -DMYSQL_TCP_PORT=3306 \                                                         //mysql 的端口默認時3306
> -DENABLE_DOWNLOADS=1 \
> -DWITH_SSL=bundled

編譯及編譯安裝(此過程時間會長一些)

[root@master mysql-5.5.24]# make && make install

修改 mysql  安裝目錄的全部者,所屬組

[root@master mysql-5.5.24]# chown -R mysql.mysql /usr/local/mysql

修改環境變量

[root@master mysql-5.5.24]# echo "PATH=$PATH:/usr/local/mysql/bin/" >> /etc/profile

[root@master mysql]# source /etc/profile                         //刷新環境變量


建立修改 my.cnf 配置文件

[root@master mysql-5.5.24]# cd /usr/local/mysql/
[root@master mysql]# ls
bin      data  include         lib  mysql-test  scripts  sql-bench
COPYING  docs  INSTALL-BINARY  man  README      share    support-files

[root@master mysql]# cp support-files/my-medium.cnf /etc/my.cnf
cp:是否覆蓋"/etc/my.cnf"? yes
[root@master mysql]# cp support-files/mysql.server /etc/init.d/mysqld

[root@master mysql]# chmod 755 /etc/init.d/mysqld                      //添加執行權限
[root@master mysql]# chkconfig --add /etc/init.d/mysqld               //將 mysql  添加爲系統使用
[root@master mysql]# chkconfig mysqld --level 35 on

初始化數據庫

[root@master mysql]# /usr/local/mysql/scripts/mysql_install_db \
> --user=mysql \                                        //指定數據庫管理員
> --ldata=/var/lib/mysql \
> --basedir=/usr/local/mysql \               //指定mysql 軟件安裝位置
> --datadir=/home/mysql                        //指定mysql 數據庫安裝位置

在配置文件中指定安裝位置

[root@master mysql]# vim /etc/init.d/mysqld

basedir=/usr/local/mysql
datadir=/home/mysql

建立軟鏈接

[root@master mysql]# ln -s /var/lib/mysql/mysql.sock /home/mysql/mysql.sock

啓動數據庫

[root@master mysql]# service mysql start
Redirecting to /bin/systemctl start mysql.service
Warning: mysql.service changed on disk. Run 'systemctl daemon-reload' to reload units.
[root@master mysql]# systemctl daemon-reload
[root@master mysql]# service mysql start
Redirecting to /bin/systemctl start mysql.service
[root@master mysql]# netstat -ntap | grep 3306                                          //查看3306端口
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      56229/mysqld

給數據庫 root 用戶設置登陸密碼,並登陸 mysql 數據庫

[root@master mysql]# mysqladmin -u root password 'abc123'
[root@master mysql]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3

四.   在三臺 服務器的 mysql 安裝完成後,分別對其進行配置。

(1)mysql 主服務器配置

[root@master mysql]# vim /etc/my.cnf

server-id       = 11                             //惟一標識,三臺服務器的 server-id  不能同樣

log-bin=mysql-bin                            //主服務器的日誌文件
log-slave-updates=true                   //從服務器的二進制文件

重啓mysql 服務

[root@master mysql]# systemctl restart mysqld.service

受權從服務器

[root@master mysql]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.

mysql> GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.213.%' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)               //受權全部從服務器複製權限,進行二進制的日誌權限管理

mysql> FLUSH PRIVILEGES;                                      //刷新
Query OK, 0 rows affected (0.01 sec)

mysql> show master status;                                   //查看主服務器狀態
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000001 |      1086|              |                  |               //文件名及位置者兩個參數記錄下來,配置同步時會使用

+-------------------+----------+--------------+------------------+                 注意:若是對數據庫 、表、數據 進行編輯,文件名和位置會變化
1 row in set (0.00 sec)

(2)mysql 從服務器 slave 01 配置

[root@slave01 mysql]# vim /etc/my.cnf

server-id       = 22
relay-log=relay-log-bin                 //IO線程經過讀取日誌要放入relay-log 中
relay-log-index=slave-relay-bin.index            //索引日誌位置

重啓mysql 服務

[root@slave01 mysql]# systemctl restart mysqld.service

mysql> change master to master_host='192.168.213.170',master_user='myslave',master_password=''123456',master_log_file='master-bin.000001',master_log_pos=1086;              //按主服務器結果更改命令中 master_log_file 和 master_log_pos 的參數  
Query OK, 0 rows affected (0.01 sec)

mysql> start slave;                                    //啓動slave
Query OK, 0 rows affected (0.00 sec)

mysql> show slave status\G;                  //查看slave狀態

Slave_IO_Running: Yes                         //讀取與重放日誌兩個參數必定爲 Yes
   Slave_SQL_Running: Yes             


(3)mysql 從服務器 slave 02 配置

[root@slave01 mysql]# vim /etc/my.cnf

server-id       = 22
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index

重啓mysql 服務

[root@slave01 mysql]# systemctl restart mysqld.service

mysql> change master to master_host='192.168.213.170',master_user='myslave',master_password=''123456',master_log_file='master-bin.000001',master_log_pos=1086;
Query OK, 0 rows affected (0.01 sec)

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

mysql> show slave status\G;

Slave_IO_Running: Yes

  Slave_SQL_Running: Yes

五.   驗證主從同步

在 主服務器上建立一個庫,看從服務器上可否同步

mysql> create database school;
Query OK, 1 row affected (0.00 sec)

在從服務器查看數據庫

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| #mysql50#.mozilla  |
| mysql              |
| performance_schema |
| schoo              |
| school             |
| test               |
+--------------------+

搭建 MySQL 讀寫分離

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

1.  在Amoeba 上安裝 Java 環境。

由於 Amoeba 是基於jdk 1.5 開發的,因此官方推薦使用jdk 1.5 或1.6 版本

[root@bogon Y2C]#systemctl stop firewalld.service                                      #關閉防禦牆

[root@bogon Y2C]#setenforce 0

[root@bogon Y2C]# cp jdk-6u14-linux-x64.bin /usr/local/                           #將壓縮包複製到 /usr/local/ 目錄下

[root@bogon Y2C]# ./jdk-6u14-linux-x64.bin                                                 #根據提示輸入yes,按回車鍵完成便可

Do you agree to the above license terms? [yes or no]

Press Enter to continue.....

[root@bogon Y2C]# mv jdk1.6.0_14/ /usr/local/jdk1.6                              #將壓縮包剪切到/usr/local/
[root@bogon Y2C]# 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@bogon Y2C]# source /etc/profile                 #從新讀取系統環境變量

2 .  安裝並配置 Amoeba 軟件

[root@bogon Y2C]# mkdir /usr/local/amoeba                                            #建立amoeba 安裝目錄
[root@bogon Y2C]# tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/              #解壓amoeba 軟件包

[root@bogon Y2C]# chmod -R 755 /usr/local/amoeba/                     #遞歸修改權限
[root@bogon Y2C]# /usr/local/amoeba/bin/amoeba                          #查看amoeba 安裝狀態
amoeba start|stop                   //顯示此內容說明 Amoeba 安裝成功

3.  配置Amoeba 讀寫分離,兩個 Slave 讀負載均衡

(1)在 Master 、slave一、slave2   數據庫中開放權限給 Amoeba 訪問

mysql> grant all on *.* to test@'192.168.213.%' identified by '123.com';
Query OK, 0 rows affected (0.00 sec)

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

[root@bogon Y2C]#cd /usr/local/amoeba/conf/

[root@bogon Y2C]#vim amoeba.xml

30                                         <property name="user">amoeba</property>              #在30行做用 ,設置客戶端鏈接anoeba 的帳戶
31
32                                         <property name="password">123456</property>      #設置客戶端鏈接amoeba 的密碼

115                 <property name="defaultPool">master</property>                          #編輯默認地址池爲名稱 master
116
117                
118                 <property name="writePool">master</property>                           #關閉註釋,寫入池名稱爲 master
119                 <property name="readPool">slaves</property>                            #關閉註釋,讀入池名稱爲 slaves

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

[root@bogon Y2C]#cd /usr/local/amoeba/conf/

[root@bogon Y2C]#vim dbServers.xml

   26                     <property name="user">test</property>                 #編輯鏈接數據庫用戶
  27                        
  28                        
  29                         <property name="password">123.com</property>        #編輯鏈接數據庫帳戶密碼

   45                <dbServer name="master"  parent="abstractServer">           #指定 master 服務器
  46                 <factoryConfig>
  47                        
  48                         <property name="ipAddress">192.168.213.170</property>      #指定主服務器的IP 地址

                           <dbServer name="slave1"  parent="abstractServer">                     #指定 slave 1 服務器
  53                 <factoryConfig>
  54                        
  55                         <property name="ipAddress">192.168.213.168</property>      #指定slave 1 服務器的IP

59         <dbServer name="slave2"  parent="abstractServer">                          #指定 slave 2 服務器
60                 <factoryConfig>
61
62                         <property name="ipAddress">192.168.213.171</property>    #指定slave 1 服務器的IP 地址
63                 </factoryConfig>
64         </dbServer>

<dbServer name="slaves" virtual="true">                                                  #設置羣集名稱 slaves
  66                 <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
  67                         <!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
  68                         <property name="loadbalance">1</property>
  69
  70                         <!-- Separated by commas,such as: server1,server2,server1 –>


  71                         <property name="poolNames">slave1,slave2</property>                  #定義羣集池成員
  72                 </poolConfig>
  73         </dbServer>

4 .  啓動 Amoeba ,器默認端口爲 tcp 8066

[root@bogon amoeba]# /usr/local/amoeba/bin/amoeba start&
[3] 5133

[root@bogon amoeba]# netstat -anpt | grep java
tcp6       0      0 127.0.0.1:38334         :::*                    LISTEN      5133/java          
tcp6       0      0 :::8066                 :::*                    LISTEN      5133/java 

測試讀寫分離  

(1)在 Client 端鏈接 Amoeba,經過代理訪問 MySQL:

[root@client ~]# mysql -uamoeba -p123 -h192.168.213.166 -P 8066

(2)在 Master 上建立表 info ,同步到曾服務器上,而後關閉曾服務器的 Slave 功能,在插入區別語句。   

mysql> use school;
Database changed

mysql> create table info (id int(10),name varchar(10));
Query OK, 0 rows affected (0.23 sec)

(3)分別關閉從服務器 slave 功能:

mysql> stop slave;
Query OK, 0 rows affected (0.01 sec)

(4)在主服務器上 school 庫中的info 表中插入一條語句

mysql> insert into info values (1,'tom');
Query OK, 1 row affected (0.12 sec)

mysql> select * from info;
+------+------+
| id   | name |
+------+------+
|    1 | tom  |

+------+------+

(5)從服務器上同步了表,手動插入其餘內容

從服務器1

mysql> insert into info values (2,'li');
Query OK, 1 row affected (0.06 sec)

從服務器2

mysql> insert into info values (3,'zh');
Query OK, 1 row affected (0.08 sec)

(6)測試讀的的客戶端查看操做,在

MySQL [school]> select * from info;                         #第一次查詢
+------+------+
| id   | name |
+------+------+
|    2 | li   |
+------+------+
1 row in set (0.06 sec)

MySQL [school]> select * from info;                        #第二次查詢
+------+------+
| id   | name |
+------+------+
|    3 | zh   |
+------+------+
1 row in set (0.44 sec)

在客戶端只能讀取曾服務器上的內容,沒法讀取主服務器上的內容,說明讀的操做在曾服務器上

(7)測試寫操做,在客戶端主機插入語句

MySQL [school]> insert into info values (5,'liu');
Query OK, 1 row affected (0.05 sec)

在客戶端查詢不到,最終只有在 Master 上才能看到這條語句,說明寫入操做在 Master 服務器上

mysql> select * from info;
+------+------+
| id   | name |
+------+------+
|    1 | tom  |
|    5 | liu  |
+------+------+

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

相關文章
相關標籤/搜索