MySQL主從復制與讀寫分離
一、簡介
MySQL主從復制和讀寫分離兩者有着緊密的聯系,只有部署好主從復制了,才能在此基礎上進行數據庫的讀寫分離。
1.MySQL支持的復制類型
a.基於語句的復制。
b.基於行的復制。
c.混合類型的復制。默認基於語句復制,當基於語句的復制無法精確復制時,就會采用基於行的復制。
2.讀寫分離
只在主服務器上寫,從服務器上讀。基本原理就是讓主數據庫處理事務性查詢,而從服務器處理select查詢。set global read_only=0;
目前常見的MySQL讀寫分離有兩種:
a.基於程序代碼內部實現
在代碼中根據select、insert進行路由分類。有點是性能好,不需要增加額外的設備作為硬件開支;缺點是需要開發人員實現,運維人員無從下手。
b.基於中間代理實現
1)MySQL-Proxy。
2)Amoeba,由陳思儒開發,作者曾就職阿里巴巴,阿里巴巴將其應用於生產環境中。這個軟件致力於mysql的分布式數據庫前端代理層,它主要為應用層訪問mysql的時候充當sql路由功能,並具備有負載均衡、高可用性、sql過濾、讀寫分離、可路由相關的到目標數據庫,可並發請求多台數據庫,不過它不支持事務和存儲過程。
二、案例環境
系統:CentOS 6.5-64
主機:
master 192.168.0.100 cmake mysql
slave1 192.168.0.101 cmake mysql
slave2 192.168.0.102 cmake mysql
Amoeba 192.168.0.110 amoeba jdk
client 192.168.0.111
三、環境准備
1.配置主機名和ip地址
root@localhost #hostname master
root@master #vim /etc/hosts
192.168.0.100 master
192.168.0.101 slave1
192.168.0.102 slave2
192.168.0.110 amoeba
192.168.0.111 client
root@master #vim /etc/sysconfig/network
HOSTNAME=master
root@master #ifconfig -a //查詢所有網卡
root@master #vim /etc/sysconfig/network-scripts/ifcfg-eth2
DEVICE=eth2
HWADDR=00:0C:29:49:0F:81
TYPE=Ethernet
UUID=d97bca82-0440-41f9-9cd0-02fe0909cee6
ONBOOT=yes
NM_CONTROLLED=yes
BOOTPROTO=static
IPADDR=192.168.0.10
NETMASK=255.255.255.0
root@master #service network restart
2.安裝NTP
NTP時間同步服務器,在主節點上搭建,主節點可以是單獨一台服務器,也可以是master,或者Amoeba服務器
root@master #mount /dev/cdrom /media/
root@master #rm -fr /etc/yum.repos/*
root@master #cat >/etc/yum.repos/local.repo<<end
>[local]
>name=cjenlet
>baseurl=file:///media/
>enabled=1
>gpgcheck=0
>end
root@master #yum -y install ntp
root@master #vim /etc/ntp.conf
server 127.127.1.0
fudge 127.127.1.0 stratum 8
root@master #service ntpd restart
root@master #service iptables stop
root@master #chkconfig iptables off
root@master #setenforce 0
root@master #vim /etc/selinux/config
SELINUX=disabled
從節點上安裝ntpdate,每台需要同步時間的服務器都要安裝
root@localhost ~#service iptables stop
root@master #chkconfig iptables off
root@localhost ~#setenforce 0
root@localhost ~#vim /etc/selinux/config
SELINUX=disabled
root@localhost ~#yum -y install ntpdate
root@localhost ~#/usr/sbin/ntpdate 192.168.0.100 //指向NTP服務器的ip地址
四、安裝MySQL數據庫
1.在master,slave1,slave2上安裝mysql
[root@master ~]# yum -y install ncurses-devel
[root@master ~]# tar xvf cmake_2_.tgz
[root@master ~]# cd cmake-2.8.6/
[root@master cmake-2.8.6]# ./configure
[root@master cmake-2.8.6]#gmake
[root@master cmake-2.8.6]#gmake install
[root@master ~]# tar xvf mysql_5_.tgz
[root@master ~]# cd mysql-5.5.22/
[root@master mysql-5.5.22]# cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DWITH_EXTRA_CHARSETS=all -DSYSCONFDIR=/etc
[root@master mysql-5.5.22]#make &&make install
2.優化調整,master,slave1,slave2都要優化
[root@master mysql-5.5.22]# cp support-files/my-medium.cnf /etc/my.cnf
[root@master mysql-5.5.22]# cp support-files/mysql.server /etc/rc.d/init.d/mysqld
[root@master mysql-5.5.22]# chmod +x /etc/rc.d/init.d/mysqld
[root@master mysql-5.5.22]# chkconfig --add mysqld
[root@master mysql-5.5.22]# cat >>/etc/profile<<end
PATH=$PATH:/usr/local/mysql/bin
end
[root@master mysql-5.5.22]# . /etc/profile
3.初始化數據庫
[root@master mysql-5.5.22]# groupadd mysql
[root@master mysql-5.5.22]# useradd -M -s /sbin/nologin mysql -g mysql
//-M不創建家目錄;-s指定shell環境;-g指定組
[root@master mysql-5.5.22]# chown -R mysql.mysql /usr/local/mysql/
[root@master mysql-5.5.22]# /usr/local/mysql/scripts/mysql_install_db --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data/ --user=mysql
//本人不小心漏打了- -user=mysql,后來重新把整條命令完整執行一遍,這樣是不對的,到時候啟動數據庫的時候會啟動失敗,建議把/usr/local/mysql/data/目錄下的所有東西刪掉,然后再完整執行這條命令
4.啟動mysql服務
[root@slave1 mysql]# service mysqld start
[root@master mysql-5.5.22]# chkconfig mysqld on
[root@master mysql-5.5.22]# mysqladmin -u root password 'abc123.' //為root用戶設置密碼
五、規划配置主從服務器,驗證主從復制。
1.配置mysql master主服務器
[root@master mysql-5.5.22]# vim /etc/my.cnf
log-bin=master-bin //修改
log-slave-updates=true //增加
server-id=11 //修改
[root@master mysql-5.5.22]# service mysqld restart
//重啟服務
[root@master mysql-5.5.22]# mysql -uroot -pabc123. //登錄數據庫
mysql> grant replication slave on *.* to myslave@'192.168.0.%' identified by 'abc123.';
// 意思是,在mysql數據庫user表中創建myslave用戶,允許其能夠以密碼‘abc123.’從
//網段為192.168.0.%訪問數據庫時有復制的權限
//奪權:
revoke replication slave on *.* from myslave@'192.168.0.%'
//mysql> grant replication slave on *.* to myslave@192.168.0.102 identified by 'abc123.';
//只給單個ip賦予權限,給ip地址改成主機名,建議先把user表的myslave對應的host改成///slave1
mysql>update user set host='slave1' where user='myslave';
mysql> flush privileges; //跟新用戶列表
mysql> show master status;
2.配置mysql slave從服務器
a. [root@slave1 mysql]# vim /etc/my.cnf
server-id = 22
//修改,server-id不能與服務器相同
relay-log=relay-log-bin
//增加
relay-log-index=slave-relay-bin.index
//增加
b. [root@slave1 mysql]# service mysqld restart //重啟服務
c. 登錄從服務器mysql數據庫,配置同步
[root@slave1 mysql]# mysql -uroot -pabc123.
mysql> change master to master_host='192.168.0.100',master_user='myslave',master_password='abc123.',master_log_file='master-bin.000001',master_log_pos=488;
//注意單引號要打全,每次設置都要先回到master主機show master status;
//在slave2從服務器上只需把上面這條命令中的slave1改為slave2,執行
d. mysql> start slave; //啟動同步
mysql> show slave status\G;
//查看slave狀態,確保以下兩個值為yes
3.驗證主從復制效果
mysql> create database cjenlet;
//主服務器上創建cjenlet數據庫
mysql> show databases;
//master,slave1,slave2,上分別查看,的到的結果是一樣的,都有新建的cjenlet數據庫存在
六、搭建mysql讀寫分離
1.環境准備,在amoeba主機上安裝java環境
[root@amoeba ~]# cp jdk_6u14.bin /usr/local/
[root@amoeba ~]#cd /usr/local
[root@amoeba local]# chmod +x /usr/local/jdk_6u14.bin
[root@amoeba local]# ./jdk_6u14.bin //按enter繼續
[root@amoeba local]# vim /etc/profile
export JAVA_HOME=/usr/local/java
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@amoeba local]# vim /etc/profile
[root@amoeba local]# java -version
2.安裝amoeba
[root@amoeba ~]# mkdir /usr/local/amoeba
[root@amoeba ~]# tar xvf amoeba_m.tgz -C /usr/local/amoeba/
[root@amoeba ~]# chmod -R 755 /usr/local/amoeba/
[root@amoeba ~]# /usr/local/amoeba/bin/amoeba
//顯示如下圖則成功
3.配置amoeba讀寫分離,兩個slave讀負載均衡
master:
mysql> grant all on *.* to test@'amoeba' identified by 'abc123.';
//只在master上給創建test用戶就可以了,因為slave1和slave2都會同步的。
//只賦予amoeba具有代理的權限,以test用戶管理數據庫,通過代理,其沒有創建用戶和給//用戶賦權的權限
4.編輯amoeba.xml配置文件
[root@amoeba ~]# vim /usr/local/amoeba/conf/amoeba.xml
//修改下圖中紅框的地方,這是設置amoeba管理密碼
//修改下圖紅框的地方,這是規划讀寫分離
5.配置dbServer.xml配置文件
[root@amoeba ~]# vim /usr/local/amoeba/conf/dbServers.xml
6.啟動amoeba
[root@amoeba ~]#/usr/local/amoeba/bin/amoeba start&
//后台運行,沒有‘&’是前台運行的意思
[root@amoeba ~]#netstat -anpl|grep java
//可以查看到amoeba的監聽端口,默認為8066,可以在amoeba.xml文件中修改端口
七、測試讀寫分離
1.客戶機通過端口訪問代理登陸mysql
cjenlet@cjenlet-u:~$ mysql -uamoeba -pabc123. -h 192.168.0.110 -P 8066
//確保客戶端有mysql客戶端工具,能夠與整個網絡互通,其他的不需要
注意:指定端口的P是大寫的,否則永遠過不去。
2.創建數據
a.本地登陸master主機mysql數據庫,創建表cjenDB
mysql> use cjenlet;
mysql> create table cjenDB (id int(10),name varchar(10),address varchar(20));
mysql> describe cjenDB; //查看表結構
//這時slave1和slave2都會同步這份數據,在它們上顯示的結果是一樣的
b.制造差異,以便后面區分讀寫分離的效果
先關掉slave1和slave2的slave功能
slave1:
mysql>stop slave;
slave2:
mysql>stop slave;
master,slave1和slave2上分別在表cjenDB上插入不同的數據
master:
mysql> insert into cjenDB values('1','cjenlet','this_is_master');
slave1:
mysql> insert into cjenDB values('2','cjenlet','this_is_slave1');
slave2:
mysql> insert into cjenDB values('3','cjenlet','this_is_slave2');
3.客戶端訪問數據庫
a.負載均衡:
mysql>use cjenlet;
mysql>select * from cjenDB;
//如果沒有出錯的話,第一次查到的結果是slave1上表cjenDB的數據
//第二次查到的結果是slave2上表cjenDB的數據,方正多次查詢結果是不一樣的,分別是slave1和slave2上的數據,這就是amoeba實現mysql負載均衡的體現。
//不過本人實現的過程中卻沒有這一現象出現,一直都是slave2的數據,不知道問題出在哪里
解決:
查看對比slave1和slave2的相關配置文件
發現slave1的/etc/hosts文件有一條打錯,導致沒有amoeba主機的ip記錄
本機的ip地址配置文件/etc/sysconfig/network-scripts/ifcfg-eth2中的DEVICE=eth2也打成DEVICE=eth2: ,多打了一個冒號
把這些弄號后,發現還是client還是select不到slave1的數據
后來推斷應該是之前的ip地址和hosts文件的出錯導致主從同步時,master主機創建test用戶時,slave1沒有同步過來,所以只要在slave1上重新創建一次test用戶即可
b.讀寫分離:
在客戶端執行
mysql>insert into cjenDB values('4','cjenletC','this_is_client');
mysql>select * from cjenDB;
//這時客戶端查到的結果是沒有這一行內容的,而master主機上查到的結果是有的。