前言
大型網站爲了軟解大量的併發訪問,除了在網站實現分佈式負載均衡,遠遠不夠。到了數據業務層、數據訪問層,若是仍是傳統的數據結構,或者只是單單靠一臺服務器來處理如此多的數據庫鏈接操做,數據庫必然會崩潰,特別是數據丟失的話,後果更是不堪設想。這時候,咱們會考慮如何減小數據庫的鏈接,下面就進入咱們今天的主題。mysql
利用主從數據庫來實現讀寫分離,從而分擔主數據庫的壓力。在多個服務器上部署mysql,將其中一臺認爲主數據庫,而其餘爲從數據庫,實現主從同步。其中主數據庫負責主動寫的操做,而從數據庫則只負責主動讀的操做(slave從數據庫仍然會被動的進行寫操做,爲了保持數據一致性),這樣就能夠很大程度上的避免數據丟失的問題,同時也可減小數據庫的鏈接,減輕主數據庫的負載。sql
下面讓咱們來看下一個圖:數據庫
在上面的模型中,Mysql-A就是主服務器,即master,Mysql-B就是從服務器,即slave。vim
在Mysql-A的數據庫事件(例如修改數據庫的sql操做語句),都會存儲到日誌系統A中,在相應的端口(默認3306)經過網絡發送給Mysql-B。Mysql-B收到後,寫入本地日誌系統B,而後一條條的將數據庫事件在數據庫Mysql-B中完成。centos
日誌系統A,是MYSQL的日誌類型中的二進制日誌,也就是專門用來保存修改數據庫表的全部動做,即bin log,注意MYSQL會在執行語句以後,釋放鎖以前,寫入二進制日誌,確保事務安全。安全
日誌系統B,不是二進制日誌,因爲它是從MYSQL-A的二進制日誌複製過來的,並非本身的數據庫變化產生的,有點接力的感受,稱爲中繼日誌,即relay log。服務器
經過上面的機制,能夠保證Mysql-A和Mysql-B的數據庫數據一致,可是時間上確定有延遲,即Mysql-B的數據是滯後的。所以,會出現這樣的問題,Mysql-A的數據庫操做是能夠併發的執行的,可是Mysql-B只能從relay log中一條一條的讀取執行。若Mysql-A的寫操做很頻繁,Mysql-B極可能就跟不上了。網絡
主從同步複製有如下幾種方式:數據結構
(1)同步複製,master的變化,必須等待slave-1,slave-2,...,slave-n完成後才能返回。併發
(2)異步複製,master只須要完成本身的數據庫操做便可,至於slaves是否收到二進制日誌,是否完成操做,不用關心。MYSQL的默認設置。
(3)半同步複製,master只保證slaves中的一個操做成功,就返回,其餘slave無論。這個功能,是由google爲MYSQL引入的。
本文說的是在centos 7系統上,實現的mysql5.7數據庫的主從同步配置,從而實現讀寫分離操做。
1 分別在兩臺centos 7系統上安裝mysql 5.7
具體的安裝步驟能夠見此連接,https://blog.csdn.net/qq_15092079/article/details/81629238。
本文中的兩臺服務器的IP地址分別爲主服務器(192.168.17.130)和從服務器(192.168.17.132)。
分別在這兩個服務器上建立test數據庫,以備後面測試。
2 master主服務器的配置
2.1 配置文件my.cnf的修改
#根據上一篇文章,編輯my.cnf文件
[root@localhost mysql]# vim /etc/my.cnf
#在[mysqld]中添加:
server-id=1
log_bin=master-bin
log_bin_index=master-bin.index
binlog_do_db=test
#備註:
#server-id 服務器惟一標識。
#log_bin 啓動MySQL二進制日誌,即數據同步語句,從數據庫會一條一條的執行這些語句。
#binlog_do_db 指定記錄二進制日誌的數據庫,即須要複製的數據庫名,若是複製多個數據庫,重複設置這個選項便可。
#binlog_ignore_db 指定不記錄二進制日誌的數據庫,即不須要複製的數據庫名,若是有多個數據庫,重複設置這個選項便可。
#其中須要注意的是,binlog_do_db和binlog_ignore_db爲互斥選項,通常只須要一個便可。
2.2 建立從服務器的用戶和權限
#進入mysql數據庫
[root@localhost mysql]# mysql -uroot -p
Enter password:
#建立從數據庫的masterbackup用戶和權限
mysql> grant replication slave on *.* to masterbackup@'192.168.17.%' identified by '123456';
#備註
#192.168.17.%通配符,表示0-255的IP均可訪問主服務器,正式環境請配置指定從服務器IP
#若將 192.168.17.% 改成 %,則任何ip都可做爲其從數據庫來訪問主服務器
#退出mysql
mysql> exit;
2.3 重啓mysql服務
[root@localhost mysql]# service mysql restart
Shutting down MySQL.... SUCCESS!
Starting MySQL. SUCCESS!
2.4 查看主服務器狀態
#進入mysql數據庫
[root@localhost mysql]# mysql -uroot -p
Enter password:
#查看主服務器狀態
mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000001 | 154 | test | | |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
3 slave從服務器的配置
3.1 配置文件my.cnf的修改
#根據上一篇文章,編輯my.cnf文件
[root@localhost mysql]# vim /etc/my.cnf
#在[mysqld]中添加:
server-id=2
relay-log=slave-relay-bin
relay-log-index=slave-relay-bin.index
#replicate-do-db=test
#備註:
#server-id 服務器惟一標識,若是有多個從服務器,每一個服務器的server-id不能重複,跟IP同樣是惟一標識,若是你沒設置server-id或者設置爲0,則從服務器不會鏈接到主服務器。
#relay-log 啓動MySQL二進制日誌,能夠用來作數據備份和崩潰恢復,或主服務器掛掉了,將此從服務器做爲其餘從服務器的主服務器。
#replicate-do-db 指定同步的數據庫,若是複製多個數據庫,重複設置這個選項便可。若在master端不指定binlog-do-db,則在slave端可用replication-do-db來過濾。
#replicate-ignore-db 不須要同步的數據庫,若是有多個數據庫,重複設置這個選項便可。
#其中須要注意的是,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數據庫
[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='master-bin.000001',master_log_pos=154;
#備註:
#master_host對應主服務器的IP地址。
#master_port對應主服務器的端口。
#master_log_file對應show master status顯示的File列:master-bin.000001。
#master_log_pos對應show master status顯示的Position列:154。
3.4 啓動slave數據同步
#啓動slave數據同步
mysql> start slave;
#中止slave數據同步(如有須要)
mysql> stop slave;
3.5 查看slave信息
mysql> show slave status\G;
Slave_IO_Running和Slave_SQL_Running都爲yes,則表示同步成功。
4 測試
(1)在主服務器上登錄mysql,且進入test數據庫,建立test表,且插入一條數據
提示:這裏最好用數據庫管理工具(如nacicat)來操做。
#建立tb_test表
create table tb_test(ID varchar(36) primary key comment '主鍵ID',MEMO varchar(500) not null comment '信息');
#插入一條數據
insert into tb_test(ID,MEMO) values('1','one test');
#提交
commit;
(2)在從服務器上登錄mysql,且進入test數據庫
你會發現從數據庫中,也出現了tb_test表,且表中還有one test數據存在,證實同步數據成功。
5 解決錯誤
若在主從同步的過程當中,出現其中一條語句同步失敗報錯了,則後面的語句也確定不能同步成功了。例如,主庫有一條數據,而從庫並無這一條數據,然而,在主庫執行了刪除這一條數據的操做,那麼從庫沒有這麼一條數據就確定刪除不了,從而報錯了。在此時的從數據庫的數據同步就失敗了,所以後面的同步語句就沒法繼續執行。
這裏提供的解決方法有兩種:
(1)在從數據庫中,使用SET全局sql_slave_skip_counter來跳過事件,跳過這一個錯誤,而後執行從下一個事件組開始。
#在從數據庫上操做
mysql > stop slave;
mysql > set global sql_slave_skip_counter=1;
mysql > start slave;
(2)在從數據庫中,從新連上主數據庫。這種操做會直接跳過中間的那些同步語句,可能會致使一些數據未同步過去的問題,但這種操做也是最後的絕招。最好就是令從數據庫與主數據庫的數據結構和數據都一致了以後,再來恢復主從同步的操做。
#在從數據庫上操做
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='master-bin.000001',master_log_pos=2050;
mysql > start slave;
#備註
#master_log_file和master_log_pos可能會不一樣,須要在主數據庫中show master status來查看
6 總結
至此,mysql數據庫的主從同步就完成了,至於讀寫分離,咱們能夠經過程序來實現,這裏簡單講解一下實現思想。
咱們能夠在主服務器建立一個數據庫用戶(出於安全,根據需求給予相應的權限)主要用於寫操做,在程序中經過這一用戶鏈接主數據庫的只用於寫操做而不用讀操做。
在從服務器上建立一個數據庫用戶(出於安全,只給予讀select的權限)主要用於讀操做,在程序中經過這一用戶鏈接從數據庫便可。
固然,也能夠找一個組件來完成MYSQL的代理,實現SQL語句的路由,這樣就不須要咱們在程序上關注哪一個數據庫是寫,哪一個數據庫是讀的了。