MySQL主從複製與讀寫分離
在實際的生產環境中,若是數據庫的讀和寫都在同一個數據庫服務中操做,不管是在安全性、高可用性仍是高併發等各個方面都是徹底不能知足實際需求的,所以,通常來講都是經過主從複製的方式來同步數據,在經過讀寫分離來提高數據庫的併發負載能力這樣的的方案來進行部署與實施的。
Mysql主從複製原理:
Mysql的主從複製和mysql的讀寫分離二者有着緊密聯繫,首先要部署主從複製,只有主從複製完成了 ,才能在此基礎上進行數據的讀寫分離。
Mysql支持的複製類型:
基於語句的複製:在主服務器上執行的SQL語句,在從服務器上執行一樣的語句。默認採用,效率高。
基於行的複製:把改變的內容複製過去,而不是把命令在從服務器上執行一遍。
混合類型的複製:默認採用基於語句的複製,當沒法精確複製時,就會採用基於行的複製。
複製到工做過程:
事務更新Master記錄二進制日誌(Binary log)
Slave將Master的Binary log複製到其中繼日誌
Slave開始一個I/O線程,在Master上打開一個普通鏈接,而後開始Binlog dump process(binlogz轉儲過程),Binlog dump process 從Master的二進制日誌中讀取事件,寫入Relay log(中繼日誌)中;
SQL slave thread (SQL從線程)從中繼日誌讀取時間,並重放其中的事件而更新Slave的數據,使其保持數據一致。
複製過程由一個很重要的限制,即複製在Slave上是串化的,也就是說Master上的並行更新操做不能再Slave上並行操做。
MySQL讀寫分離原理:
讀寫分離就是隻在主服務器上寫,只在從服務器上讀。
基本的原理是讓主數據庫處理事務性查詢,而從數據庫處理select查詢。數據庫複製被用來把 事務性查詢致使的變動同步到集羣中的從數據庫。
目前比較常見的MySQL讀寫分離分爲兩種:
基於程序代碼內部實現:在代碼中根據select、insert進行路由分類,目前應用最普遍。
基於中間代理層實現:代理通常位於客戶端和服務器之間,代理服務器接到客戶端請求後經過判斷後轉發到後端數據庫,有兩個代理程序:
MySQL-Proxy
Amoeba
首先創建MYSQL
MySQL的編譯安裝
⦁ 準備工做
確認沒有使用RPM方式安裝mysql-server、mysql(若是存在mysql,則rpm -e mysql --nodeps刪除)
查看是否安裝:#rpm -q mysql-server mysql
package mysql-server is not installed
package mysql is not installed
安裝光盤自帶的ncurses- devel包
Mount /dev/cdrom /media/cdrom
rpm -ivh /media/cdrom/Packages/ncurses-devel-5.7-3.20090208.el6.x86_64.rpm
安裝cmake包
#tar zxf cmake-2.8.6.tar.gz
#cd cmake-2.8.6
# ./configure
# gmake && gmake install
⦁ 源碼編譯及安裝
# groupadd mysql
# useradd -M -s /sbin/nologin mysql -g mysql
# tar zxf mysql-5.5.22.tar.gz -C /usr/src/
# cd /usr/src/mysql-5.5.22/
#cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DSYSCONFDIR=/etc -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DWITH_EXTRA_CHARSETS=all
[root@www mysql-5.5.22]# make
[root@www mysql-5.5.22]# make install
⦁ 安裝後的其餘調整
[root@www ~]# chown -R mysql:mysql /usr/local/mysql
[root@www mysql-5.5.22]# cp support-files/my-medium.cnf /etc/my.cnf
[root@wwwmysql-5.5.22]# /usr/local/mysql/scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data/
[root@www mysql-5.5.22]# PATH=$PATH:/usr/local/mysql/binjava
⦁ 添加爲系統服務
以便經過chkconfig進行管理
# cp support-files/mysql.server /etc/rc.d/init.d/mysqld
# chmod +x /etc/rc.d/init.d/mysqld
# chkconfig --add mysqld
⦁ 啓動mysqld服務,並查看運行狀態
# service mysqld start
Starting MySQL............ [肯定]
# /etc/init.d/mysqld status
MySQL running (56956) [肯定]
# netstat -anpt | grep mysqld
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 56956/mysqld 查看服務端口,默認爲3306
⦁ 訪問MySQL數據庫
鏈接並登陸到MySQL操做環境
mysql -u 用戶名 [-p]
提示符:mysql>
設置數據庫用戶的密碼
mysqladmin -u root [-p] password 新密碼
退出MySQL操做環境
mysql> exitnode
案例:
代理服務器amoeba 主服務器master 從服務器slave 客戶機client
搭建主從複製
在主服務器master搭建時間同步服務器
#rpm –q ntp
#vim /etc/ntp.conf
Server 127.127.1.0 #NTPD把本地主機的時鐘也看做外部時鐘源來處理,分配的地址是127.127.1.0
Fudge 127.127.1.0 stratum 8
#service ntpd restart
NTPD的運行過程
NTPD啓動後,stratum值初始是0,此時NTPD接收到NTP請求,回覆Sstratum字段爲0的NTP包,客戶端接收後,發現stratum字段無效,拒絕更新時間,形成時間更新失敗。
幾分鐘 後,NTPD從上級服務器獲取到了更新,設置了正確的stratum,回覆stratum字段爲n+1的NTP包,客戶端接收後,確認stratum有效,成功進行時間跟新。
在NTPD上級服務器不可用的狀況下,NTPD將本機時鐘服務模擬爲一個上級NTP服務器,地址使用環回127.127.1.0,服務啓動幾分鐘後,NTPD從127.127.1.0更新了時鐘,設置了有效的stratum,客戶端接收後,陳宮進行時間更新。
從服務器slave進行時間同步 :
#rpm -q ntpdate
#ntpdate 192.168.11.6
配置Master主服務器
#vim /etc/my.cnf
Server-id =213 //id號隨便
Log-bin=master-bin
Log-slave-updates=true
#mysql -u root –p
Mysql>GRANT REPLICATION SLAVE ON *.* TO ‘myslave’@’192.168.11.10.%’ IDENTIFIED BY’123456’;
Mysql>FLUSH PRIVILEGES;
Mysql>show master status;
Service mysqld restart
配置slave從服務器
#vim /etc/my.cnf
Server-id =354
Relay-log=relay-log-bin
Relay-log-index=slave-relay-bin.index
#service mysqld restart
#mysql -u root –p
Mysql>change master to master_host=’192.168.11.78’,master_user=’myslave’,master_password=’123456’,master_log_file=’master-bin,0000001’,master_log_pos=338;
Mysql>start slave;
Mysql>show slave status\G;
Slave_IO_Running:Yes
Slave_SQL_Running:Yes
驗證主服務器與從服務器數據同步
在主服務器上建立數據庫
Mysql>create database db_test;
在從服務器上查看數據庫
Mysql>show databases;
搭建MySQL讀寫分離
在代理服務器Amoeba上安裝java環境
上傳jdk1.6版本jdk-6u14-linusx-x64.bin
#chmod +x /usr/local/jdk-6u14-linux-x64.bin
#cd /usr/local
#./jdk-6u14-linux-x64.bin
# mv jdk1.6.0_14/ /usr/local/jdk1.6
# vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=$CLASSPATH:$JAVA_HOME/bin:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba/
# source /etc/profile
# java -versioon
Unrecognized option: -versioon
Could not create the Java virtual machine.
# java -version
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
Java HotSpot(TM) 64-Bit Server VM (build 14.0-b16, mixed mode)
安裝並配置Amoeba軟件
# mkdir /usr/local/amoeba
# tar zxf /root/amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba
# chmod -R 755 /usr/local/amoeba/
# /usr/local/amoeba/bin/amoeba
amoeba start|stop
配置Amoeba讀寫分離,兩個slave讀負載均衡
在每一個SQL上開發全新給Amoeba訪問
Mysql>grant all on *.* to test@’192.168.11.%’ identified by ‘123456’;
#vim /usr/local/amoeba/conf/amoeba.xml
<property name=」authenticator」>
<bean class=」com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator」>
<property name=」use」>amoeba</property>
<property name=」defaultPool」>master</property>
<property name=」writePool」>master</property>
<property name=」readPool」>slaves</property>
#vim /usr/local/amoeba/conf/dbServers.xml
<property name=」user」>test</property>
<property name=」password」>123456</property>
<dbServer name=」’master」 paren=」abstractServer」>
<property name=」ipAddress」>192.168.11.78</property>
<dbServer name=」slave1」 parent=」abstractServer」>
<property name=」ipAddress」>192.168.11.74</property>
<dbServer name=」slave1」 parent=」abstractServer」>
<property name=」ipAddress」>192.168.11.74</property>
<property name=」poolNames」>slave1,slave2</property>
啓動amoeba
#/usr/local/amoeba/bin/amoeba start
測試:
在Client主機上安裝mysql並經過代理訪問Mysql
#yum –y install mysql
#mysql –u amoeba –p123456 –h 192.168.10.11 –P8066
在主服務器Master上建立表
Mysql>use db_test;
Mysql>create table zang(id int(10),name varchar(10),address varchar(20));
在從服務器中止slave
Mysql>stop slave;
在主服務建立數據
Mysql>insert into zang values(‘1’,’zhang’,’this_is_master’);
從服務器建立數據
Mysql>use db_test;
Mysql>insert into zang values(‘2’,’zhang’,’this_is_slave1’);
在Client查詢
Mysql>use db_test;
Mysql>select * from zang;
Mysql>insert into zang values(‘3’,’zhang’,’this_is_amoeba’)mysql