前言
大型站點除了在網(wǎng)站上實現(xiàn)分布式負載平衡外,還不夠,以平滑地解決大量并發(fā)訪問。
到了數(shù)據(jù)業(yè)務層、數(shù)據(jù)訪問層,如果還是傳統(tǒng)的數(shù)據(jù)結構,或者只是單單靠一臺服務器來處理如此多的數(shù)據(jù)庫連接操作,數(shù)據(jù)庫必然會崩潰,特別是數(shù)據(jù)丟失的話,后果更是不堪設想。這時候,我們會考慮如何減少數(shù)據(jù)庫的連接,下面就進入我們今天的主題。利用主從數(shù)據(jù)庫來實現(xiàn)讀寫分離,從而分擔主數(shù)據(jù)庫的壓力。在多個服務器上部署mysql,將其中一臺認為主數(shù)據(jù)庫,而其他為從數(shù)據(jù)庫,實現(xiàn)主從同步。其中主數(shù)據(jù)庫負責主動寫的操作,而從數(shù)據(jù)庫則只負責主動讀的操作(slave從數(shù)據(jù)庫仍然會被動地進行寫操作,為了保持數(shù)據(jù)一致性),這樣就可以很大程度上的避免數(shù)據(jù)丟失的問題,同時也可減少數(shù)據(jù)庫的連接,減輕主數(shù)據(jù)庫的負載。
下面讓我們來看下一個圖:
在上面的模型中,Mysql-A就是主服務器,即master,Mysql-B就是從服務器,即slave。
在Mysql-A的數(shù)據(jù)庫事件(例如修改數(shù)據(jù)庫的sql操作語句),都會存儲到日志系統(tǒng)A中,在相應的端口(默認3306)通過網(wǎng)絡發(fā)送給Mysql-B。Mysql-B收到后,寫入本地日志系統(tǒng)B,然后一條條地將數(shù)據(jù)庫事件在數(shù)據(jù)庫Mysql-B中完成。
日志系統(tǒng)A,是MYSQL的日志類型中的二進制日志,也就是專門用來保存修改數(shù)據(jù)庫表的所有動作,即bin log,注意MYSQL會在執(zhí)行語句之后,釋放鎖之前,寫入二進制日志,確保事務安全。
日志系統(tǒng)B,不是二進制日志,由于它是從MYSQL-A的二進制日志復制過來的,并不是自己的數(shù)據(jù)庫變化產(chǎn)生的,有點接力的感覺,稱為中繼日志,即relay log。
通過上面的機制,可以保證Mysql-A和Mysql-B的數(shù)據(jù)庫數(shù)據(jù)一致,但是時間上肯定有延遲,即Mysql-B的數(shù)據(jù)是滯后的。因此,會出現(xiàn)這樣的問題,Mysql-A的數(shù)據(jù)庫操作是可以并發(fā)的執(zhí)行的,但是Mysql-B只能從relay log中一條一條的讀取執(zhí)行。若Mysql-A的寫操作很頻繁,Mysql-B很可能就跟不上了。
主從同步復制有以下幾種方式:
(1)同步復制,master的變化,必須等待slave-1,slave-2,...,slave-n完成后才能返回。
(2)異步復制,master只需要完成自己的數(shù)據(jù)庫操作即可,至于slaves是否收到二進制日志,是否完成操作,不用關心。MYSQL的默認設置。
(3)半同步復制,master只保證slaves中的一個操作成功,就返回,其他slave不管。這個功能,是由google為MYSQL引入的。
本文說的是在centos 7系統(tǒng)上,實現(xiàn)的my數(shù)據(jù)庫的主從同步配置,從而實現(xiàn)讀寫分離操作。
1 分別在兩臺centos 7系統(tǒng)上安裝mysql 5.7
具體的安裝步驟可以見此鏈接,。
本文中的兩臺服務器的IP地址分別為主服務器(192.168.17.130)和從服務器(192.168.17.132)。
分別在這兩個服務器上創(chuàng)建test數(shù)據(jù)庫,以備后面測試。
2 master主服務器的配置
2.1 配置文件my.cnf的修改
#根據(jù)上一篇文章,編輯my.cnf文件 [root@localhost mysql]# vim /etc #在[mysqld]中添加: server-id=1 log_bin=master-bin log_bin_index=ma binlog_do_db=test #備注: #server-id 服務器唯一標識。 #log_bin 啟動MySQL二進制日志,即數(shù)據(jù)同步語句,從數(shù)據(jù)庫會一條一條的執(zhí)行這些語句。 #binlog_do_db 指定記錄二進制日志的數(shù)據(jù)庫,即需要復制的數(shù)據(jù)庫名,如果復制多個數(shù)據(jù)庫,重復設置這個選項即可。 #binlog_ignore_db 指定不記錄二進制日志的數(shù)據(jù)庫,即不需要復制的數(shù)據(jù)庫名,如果有多個數(shù)據(jù)庫,重復設置這個選項即可。 #其中需要注意的是,binlog_do_db和binlog_ignore_db為互斥選項,一般只需要一個即可。
2.2 創(chuàng)建從服務器的用戶和權限
#進入mysql數(shù)據(jù)庫 [root@localhost mysql]# mysql -uroot -p Enter password: #創(chuàng)建從數(shù)據(jù)庫的masterbackup用戶和權限 mysql> grant replication slave on *.* to masterbackup@'192.168.17.%' identified by '123456'; #備注 #192.168.17.%通配符,表示0-255的IP都可訪問主服務器,正式環(huán)境請配置指定從服務器IP #若將 192.168.17.% 改為 %,則任何ip均可作為其從數(shù)據(jù)庫來訪問主服務器 #退出mysql mysql> exit;
2.3 重啟mysql服務
[root@localhost mysql]# service mysql restart Shutting down MySQL.... SUCCESS! Starting MySQL. SUCCESS!
2.4 查看主服務器狀態(tài)
#進入mysql數(shù)據(jù)庫 [root@localhost mysql]# mysql -uroot -p Enter password: #查看主服務器狀態(tài) mysql> show master status; +-------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +-------------------+----------+--------------+------------------+-------------------+ | ma | 154 | test | | | +-------------------+----------+--------------+------------------+-------------------+ 1 row in set sec)
3 slave從服務器的配置
3.1 配置文件my.cnf的修改
#根據(jù)上一篇文章,編輯my.cnf文件 [root@localhost mysql]# vim /etc #在[mysqld]中添加: server-id=2 relay-log=slave-relay-bin relay-log-index= #replicate-do-db=test #備注: #server-id 服務器唯一標識,如果有多個從服務器,每個服務器的server-id不能重復,跟IP一樣是唯一標識,如果你沒設置server-id或者設置為0,則從服務器不會連接到主服務器。 #relay-log 啟動MySQL二進制日志,可以用來做數(shù)據(jù)備份和崩潰恢復,或主服務器掛掉了,將此從服務器作為其他從服務器的主服務器。 #replicate-do-db 指定同步的數(shù)據(jù)庫,如果復制多個數(shù)據(jù)庫,重復設置這個選項即可。若在master端不指定binlog-do-db,則在slave端可用replication-do-db來過濾。 #replicate-ignore-db 不需要同步的數(shù)據(jù)庫,如果有多個數(shù)據(jù)庫,重復設置這個選項即可。 #其中需要注意的是,replicate-do-db和replicate-ignore-db為互斥選項,一般只需要一個即可。
3.2 重啟mysql服務
[root@localhost mysql]# service mysql restart Shutting down MySQL.... SUCCESS! Starting MySQL. SUCCESS!
3.3 連接master主服務器
#進入mysql數(shù)據(jù)庫 [root@localhost mysql]# mysql -uroot -p Enter password: #連接master主服務器 mysql> change master to master_host='192.168.17.130',master_port=3306,master_user='masterbackup',master_password='123456',master_log_file='ma',master_log_pos=154; #備注: #master_host對應主服務器的IP地址。 #master_port對應主服務器的端口。 #master_log_file對應show master status顯示的File列:ma。 #master_log_pos對應show master status顯示的Position列:154。
3.4 啟動slave數(shù)據(jù)同步
#啟動slave數(shù)據(jù)同步 mysql> start slave; #停止slave數(shù)據(jù)同步(若有需要) mysql> stop slave;
3.5 查看slave信息
mysql> show slave status\G;
Slave_IO_Running和Slave_SQL_Running都為yes,則表示同步成功。
4 測試
(1)在主服務器上登陸mysql,且進入test數(shù)據(jù)庫,創(chuàng)建test表,且插入一條數(shù)據(jù)
提示:這里最好用數(shù)據(jù)庫管理工具(如nacicat)來操作。
#創(chuàng)建tb_test表 create table tb_test(ID varchar(36) primary key comment '主鍵ID',MEMO varchar(500) not null comment '信息'); #插入一條數(shù)據(jù) insert into tb_test(ID,MEMO) values('1','one test'); #提交 commit;
(2)在從服務器上登陸mysql,且進入test數(shù)據(jù)庫
你會發(fā)現(xiàn)從數(shù)據(jù)庫中,也出現(xiàn)了tb_test表,且表中還有one test數(shù)據(jù)存在,證明同步數(shù)據(jù)成功。
5 解決錯誤
若在主從同步的過程中,出現(xiàn)其中一條語句同步失敗報錯了,則后面的語句也肯定不能同步成功了。例如,主庫有一條數(shù)據(jù),而從庫并沒有這一條數(shù)據(jù),然而,在主庫執(zhí)行了刪除這一條數(shù)據(jù)的操作,那么從庫沒有這么一條數(shù)據(jù)就肯定刪除不了,從而報錯了。在此時的從數(shù)據(jù)庫的數(shù)據(jù)同步就失敗了,因此后面的同步語句就無法繼續(xù)執(zhí)行。
這里提供的解決方法有兩種:
(1)在從數(shù)據(jù)庫中,使用SET全局sql_slave_skip_counter來跳過事件,跳過這一個錯誤,然后執(zhí)行從下一個事件組開始。
#在從數(shù)據(jù)庫上操作 mysql > stop slave; mysql > set global sql_slave_skip_counter=1; mysql > start slave;
(2)在從數(shù)據(jù)庫中,重新連上主數(shù)據(jù)庫。這種操作會直接跳過中間的那些同步語句,可能會導致一些數(shù)據(jù)未同步過去的問題,但這種操作也是最后的絕招。最好就是令從數(shù)據(jù)庫與主數(shù)據(jù)庫的數(shù)據(jù)結構和數(shù)據(jù)都一致了之后,再來恢復主從同步的操作。
#在從數(shù)據(jù)庫上操作 mysql > stop slave; mysql> change master to master_host='192.168.17.130',master_port=3306,master_user='masterbackup',master_password='123456',master_log_file='ma',master_log_pos=2050; mysql > start slave; #備注 #master_log_file和master_log_pos可能會不同,需要在主數(shù)據(jù)庫中show master status來查看
6 總結
至此,mysql數(shù)據(jù)庫的主從同步就完成了,至于讀寫分離,我們可以通過程序來實現(xiàn),這里簡單講解一下實現(xiàn)思想。
我們可以在主服務器創(chuàng)建一個數(shù)據(jù)庫用戶(出于安全,根據(jù)需求給予相應的權限)主要用于寫操作,在程序中通過這一用戶連接主數(shù)據(jù)庫的只用于寫操作而不用讀操作。
在從服務器上創(chuàng)建一個數(shù)據(jù)庫用戶(出于安全,只給予讀select的權限)主要用于讀操作,在程序中通過這一用戶連接從數(shù)據(jù)庫即可。
當然,也可以找一個組件來完成MYSQL的代理,實現(xiàn)SQL語句的路由,這樣就不需要我們在程序上關注哪個數(shù)據(jù)庫是寫,哪個數(shù)據(jù)庫是讀的了。
————————————————
原文鏈接:
1.《mysql數(shù)據(jù)庫的主從同步,實現(xiàn)讀寫分離》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡信息知識,僅代表作者本人觀點,與本網(wǎng)站無關,侵刪請聯(lián)系頁腳下方聯(lián)系方式。
2.《mysql數(shù)據(jù)庫的主從同步,實現(xiàn)讀寫分離》僅供讀者參考,本網(wǎng)站未對該內(nèi)容進行證實,對其原創(chuàng)性、真實性、完整性、及時性不作任何保證。
3.文章轉(zhuǎn)載時請保留本站內(nèi)容來源地址,http://f99ss.com/gl/3142264.html