mysql的主從複製以及讀寫分離
前言:我們前面搭建過LAMP和LNMP,做過了web服務器羣集和熱備,web服務器壞了我們是不怕了,但是我們要知道,網站的數據有很多是存儲在數據庫裏面的,例如註冊的會員,發的文章,購物的訂單等信息。當然我們可以給數據庫做備份,但是如果每天00:00做一次備份,那麼如果在23:59數據丟失了,那麼就會丟失一天的數據,有沒有一種方法能實現實時備份,就是說有數據產生就立即備份,答案當然是有,也就是今天我們要學習的mysql主從複製。有點類似於前面我們學習過的rsync,但是不同的是rsync是對磁盤文件做備份,而mysql主從複製是對數據庫中的數據,語句做備份。另外讀寫分離主要是爲了優化數據庫。下面把實驗給大家做一遍。
一、mysql主從複製的工作原理
1、mysq支持的複製類型
1)基於語句的複製。在服務器上執行sql語句,在從服務器上執行同樣的語句,mysql默認採用基於語句的複製,執行效率高。
2)基於行的複製。把改變的內容複製過去,而不是把命令在從服務器上執行一遍。
3)混合類型的複製。默認採用基於語句的複製,一旦發現基於語句無法精確複製時,就會採用基於行的複製。
原理工作試圖:
通俗易懂的說法就是:
(1)在主MySQL服務器數據修改之後數據文件記錄在Binary log日誌當中
(2)從服務器的i/o線程連接到主MySQL服務器的Binary log的日誌當中獲取當中發生變化的數據內容
(3)將獲取到的內容寫入到自己的Relay log日誌當中
(4)通過從服務器的自身sql線程讀取Relay log日誌當中的內容進行同步
(5)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線程將這些事件寫入中繼日誌。
3)Sql slave thread(sql從線程)處理該過程的最後一步,sql線程從中繼日誌讀取事件,並重放其中的事件而更新slave數據,使其與master中的數據一致,只要該線程與I/O線程保持一致,中繼日誌通常會位於os緩存中,所以中繼日誌的開銷很小。
3、mysql讀寫分離原理
讀寫分離就是在主服務器上修改,數據會同步到從服務器,從服務器只能提供讀取數據,不能寫入,實現備份的同時也實現了數據庫性能的優化,以及提升了服務器安全。
接下來進行主從複製的案例如下圖:
搭建mysql主從複製
1.建立時間同步環境,在主節點上搭建時間同步服務器
1)安裝NTP
[root@centos2 ~]# yum -y install ntp
2)配置NTP
[root@centos2 ~]# vim /etc/ntp.conf
server 127.127.1.0 //上游時間服務器爲本機
fudge 127.127.1.0 stratum 8//允許與上級時間服務器的時間偏移
3)重啓服務
[root@centos2 ~]# service ntpd restart
2.在從節點上進行時間同步(mysql從服務器兩臺都如此)
[root@centos3 ~]# yum -y install ntpdate
[root@centos3 ~]# /usr/sbin/ntpdate 192.168.1.2
3.關閉每臺服務器防火牆 service iptables stop
4.安裝mysql過程略 本節內容不在講解mysql的安裝可以查看本人的mysql技術文檔和LNMP;LAMP文檔;裏面有詳細的內容
5.啓動mysql
6.配置mysql主服務器
1)在/etc/my.cnf中修改或增加下面內容
server-id = 11 //修改
log-bin=master-bin //修改,啓用二進制日誌,日誌文件名稱前綴
log-slave-updates=true //增加,允許從服務器複製
2)重啓mysql服務
[root@centos2 ~]# service mysqld restart
3)登錄mysql程序,給從服務器以授權
[root@centos2 ~]# mysql -u root -p
mysql> grant replication slave on *.* to 'myslave'@'192.168.1.%' identified by '123456';
mysql> flush privileges;
mysql> show master status;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000007 | 337| | |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
7.配置兩臺從服務器
1)在第一臺從服務器/etc/my.cnf中修改或增加下面內容
server-id = 22 //修改
relay-log=relay-log-bin //增加
relay-log-index=slave-relay-bin.index //增加
2)重啓mysql服務
[root@centos3 ~]# service mysqld restart
3)第二臺從服務器只是server-id不同其他都和第一臺一樣
server-id = 33
完成後重啓mysql服務
4)登錄mysql,配置同步
mysql>change to master master_host='192.168.1.2',master_user='myslave',master_password='123456',master_log_file='master-bin.000002',master_log_pos=412; 可以變動
5)啓動同步
mysql> start slave;
6)查看slave狀態,確保以下兩個至爲YES
mysql> show slave status \G;
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
7)驗證主從複製效果
①在主、從服務器上登錄mysql
[root@centos2 ~]# mysql -u root -p
②在主服務器上新建數據庫db_test
mysql> create database db_tese;
③在兩臺從服務器上查看數據庫
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db_test |
| mysql |
| performance_schema |
| test |
+--------------------+
5 rows in set (0.02 sec)
實驗二、構建mysql讀寫分離,此內容爲讀寫分離:
1.在主機amoeba上安裝java環境
[root@centos1 ~]# cp /mnt/jdk-6u14-linux-x64.bin /usr/local/
[root@centos1 ~]# chmod +x /usr/local/jdk-6u14-linux-x64.bin
[root@centos1 local]# cd /usr/local/
[root@centos1 local]# ./jdk-6u14-linux-x64.bin //根據提示按回車和yes即可
[root@centos1 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@centos1 local]# mv jdk1.6.0_14/ /usr/local/jdk1.6
[root@centos1 local]# java -version
java version "1.6.0_14
OpenJDK Runtime Environment (rhel-2.4.3.3.el6-x86_64 u45-b15)
OpenJDK 64-Bit Server VM (build 24.45-b08, mixed mode)
java環境已經成功
安裝並配置amoeba軟件
[root@centos1 local]# mkdir /usr/local/amoeba
[root@centos1 local]# tar zxf /mnt/amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba
[root@centos1 local]# chmod -R 755 /usr/local/amoeba/
[root@centos1 local]# /usr/local/amoeba/bin/amoeba
3.配置amoeba讀寫分離,兩個slave讀負載均衡
①master、slave1和slave2中開放權限給amoeba訪問
mysql> grant all on *.* to 'test'@'192.168.1.%' identified by '123.com';
②編輯amoeba.xml配置文件.注意修改紅色下劃線處
28 <property name="user">amoeba</property>
30 <property name="password">123456</property>
113 <property name="defaultPool">master</property>
115 <property name="writePool">master</property>
116 <property name="readPool">slaves</property>
③編輯dbServer.xml配置文件
26<property name="user">test</property>
29<property name="password">123.com</property>
45 <dbServer name="master" parent="abstractServer">
46<factoryConfig>
47 <!-- mysql ip -->
48 <property name="ipAddress">192.168.1.2</property>
49 </factoryConfig>
50 </dbServer>
52 <dbServer name="slave1" parent="abstractServer">
53 <factoryConfig>
54 <!-- mysql ip -->
55<property name="ipAddress">192.168.1.3</property>
56</factoryConfig>
57</dbServer>
58<dbServer name="slave2" parent="abstractServer">
59<factoryConfig>
60<!-- mysql ip -->
61<property name="ipAddress">192.168.1.4</property>
62</factoryConfig>
63</dbServer>
65<dbServer name="slaves" virtual="true">
66<poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
67 <!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
68 <property name="loadbalance">1</property>
70<!-- Separated by commas,such as: server1,server2,server1 -->
71<property name="poolNames">slave1,slave2</property>
72</poolConfig>
73</dbServer>
④配置無誤後,可以啓動amoeba軟件,默認端口爲tcp8066
[root@centos1 amoeba]# bin/amoeba start &
4.測試
①在client主機上
l #yum -y install mysql
l 然後通過代理訪問mysql 本機如果已安裝可不用安裝
l [root@centos1 ~]# mysql -u amoeba -p123456 -h 192.168.1.1 -P8066 (-P爲大寫)
②在master上創建一個表,同步到各個從服務器上,然後關掉各從服務器的slave功能,再插入區別語句
mysql> use db_lxf
mysql> create table zang(id int(10),name varchar(10),address varchar(20));
③分別在兩臺從服務器上
mysql>stop slave;
④然後在主服務器上插入數據
mysql> insert inot zang values('1','zhang','this_is_master');
⑤從服務器同步了表,手動插入其他內容
slave1:
mysql> use db_lxf
mysql> insert into zang values('2','zhang','this_is_slave1');
slave2:
mysql> use db_lxf
mysql> insert into zang values('2','zhang','this_is_slave2');
⑥測試讀操作
在client主機上第一次查詢的結果如下:
mysql> use db_lxf
mysql> select * from zang;
+------+-------+----------------+
| id | name | address |
+------+-------+----------------+
| 3 | zhang | this_is_slave1 |
+------+-------+----------------+
1 row in set (0.03 sec)
第二次查詢結果如下:
mysql> select * from zang;
+------+-------+----------------+
| id | name | address |
+------+-------+----------------+
| 2 | zhang | this_is_slave2 |
測試寫操作在客戶端:
mysql> insert into zang values('4','zhang','write_test');
但是在客戶機上查詢不到
最終只能在主服務器上才能看到這條語句內容,說明寫操作在master服務器上
mysql> select * from zang;
+------+-------+----------------+
| id | name | address |
+------+-------+----------------+
| 1 | zhang | this_is_master |
| 4 | zhang | write_test |
+------+-------+----------------+
2 rows in set (0.03 sec)
在主服務器mysql上進行驗證:
其他兩個從服務器上查看: