前言¶
我們用的在這篇文章《在CentOS上使用Nginx和Tomcat搭建高可用高併發網站》使用的只有一個MySQL數據庫。
- 從安全角度來說這是非常不安全的,比如這個數據庫服務器磁盤突然損壞了,裏面的數據全部丟失了。這種情況如果一開始只是部署一個數據庫的話就非常危險了,這表明我們要丟失全部數據,而數據對網站來說是最最重要的,所以我們要保證數據的安全。
- 從性能上來說,我們在《CentOS下安裝和使用Mycat實現分佈式數據庫》這篇文章中介紹了分佈式數據庫,性能雖然比單個數據庫的性能要好。但是當使用分佈式數據庫時,數據量還是很大,在查詢數據時,可能會變得非常慢,導致鎖表,一旦鎖表就無法寫入數據,就會影響其他用戶的寫入數據的操做。所以就需要讀寫分離,主(master)數據庫負責寫入數據,從(slave)數據庫負責查詢數據,就算從(slave)數據庫在查詢數據時出現了鎖表,也不會影響到主(master)數據庫的的寫入操作,最多也是從(slave)數據庫的數據更新的慢一些。基於這種情況,就出現了主從複製這個技術。
主從複製: 就是有兩個數據庫服務器,一個是主(master)數據庫服務器,另一個是從(slave)數據庫服務器。當主(master)數據庫有數據寫入,包括插入、刪除、修改,都會在從(slave)數據庫上操作一次。這樣的操作下,主從(slave)數據庫的數據都是一樣的,就相當於時刻在做數據備份,就算主(master)數據庫的數據全部丟失了,還有從(slave)數據庫的數據,我們就可以把從(slave)數據庫的數據導出來進行數據恢復。
主從複製原理主要有三個線程不斷在工作:
- 主(master)數據庫啓動bin二進制日誌,這樣會有一個Dump線程,這個線程是把主(master)數據庫的寫入操作都會記錄到這個bin的二進制文件中。
- 然後從(slave)數據庫會啓動一個I/O線程,這個線程主要是把主(master)數據庫的bin二進制文件讀取到本地,並寫入到中繼日誌(Relay log)文件中。
- 最後從(slave)數據庫其他SQL線程,把中繼日誌(Relay log)文件中的事件再執行一遍,更新從(slave)數據庫的數據,保持主從數據一致。

安裝MySQL¶
要實現主從複製就需要兩臺數據庫服務器,可以參考這篇文章《在CentOS上使用Nginx和Tomcat搭建高可用高併發網站》安裝兩個CentOS虛擬機。它們的信息如下:
| 主機名 | IP地址 | 任務角色 | 數據庫 |
| :----: | :----: | :----: | :----: |
|node2 | 192.168.204.122 | master | MySQL
|node3 | 192.168.204.123 | slave | MySQL
然後我們在node2和node3機器上安裝MySQL數據庫。操作如下:
首先關閉防火牆,方便之後的操作。
service iptables stop
我們可以使用以下命令查看MySQL是否安裝了:
rpm -qa | grep mysql
應該會輸出一下日誌:
[root@localhost ~]# rpm -qa | grep mysql
mysql-libs-5.1.71-1.el6.x86_64
然後我們可以先移除這個MySQL,重新安裝一個:
yum -y remove mysql-libs-5.1.71-1.el6.x86_64
移除之前的MySQL之後,可以重新安裝MySQL:
yum -y install mysql-server mysql mysql-devel
最後再查看安裝情況:
rpm -qa | grep mysql
正常的應該會輸出以下信息:
mysql-5.1.73-8.el6_8.x86_64
mysql-libs-5.1.73-8.el6_8.x86_64
mysql-server-5.1.73-8.el6_8.x86_64
mysql-devel-5.1.73-8.el6_8.x86_64
安裝完成之後,我們可以對MySQL數據庫進行一些配置:
vim /etc/my.cnf
主要也是在[mysqld]下加上下面兩行代碼,主要是設置編碼方式和不區分字母大小寫。
default-character-set=utf8 # 設置編碼方式
lower_case_table_names=1 # 不區分字母大小寫
修改之後的配置文件如下:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
default-character-set=utf8 # 設置編碼方式
lower_case_table_names=1 # 不區分字母大小寫
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
配置完成之後,我們直接啓動MySQL:
service mysqld start
然後我們可以把MySQL服務添加到開機自動啓,這樣就不用每次都啓動了。
chkconfig mysqld on
我們可以使用以下的命令查看是否成功添加到開機服務中了。
chkconfig --list | grep mysqld
設置MySQL數據庫的密碼:
mysqladmin -u root password 'root'
登錄數據庫,輸入該命令之後還有輸入數據庫的密碼,這個密碼就是上面設置的root:
mysql -u root -p
爲了讓Mycat可以連接MySQL數據庫,我們還要設置數據庫支持遠程連接,在登錄數據庫之後輸入以下兩條命令:
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
mysql> FLUSH PRIVILEGES;
配置主從複製¶
主(master)數據庫主要做以下幾件事情:
- 開啓bin二進制日誌;
- 配置唯一的server-id;
- 獲得主(master)數據庫二進制日誌文件名及位置;
- 創建一個用於slave和master通信的用戶賬號,這個可以使用我們已經設置了的遠程訪問賬號。
開啓bin二進制日誌和配置server-id都是在配置文件/etc/my.cnf中進行設置。在[mysqld]下加上下面兩行代碼,完成這兩個配置:
log-bin=mysql-bin # 開啓二進制日誌
server-id=1 # 設置server-id
除了配置這些重要的信息,我們還可以配置其他的信息,比如不要複製哪些數據庫,或者是隻是複製哪些數據庫。配置如下:
# 不同步哪些數據庫
binlog-ignore-db = mysql
binlog-ignore-db = test
binlog-ignore-db = information_schema
# 只同步哪些數據庫,除此之外,其他不同步
# binlog-do-db = game
整個配置完成之後是以下這個樣子的:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
default-character-set=utf8 # 設置編碼方式
lower_case_table_names=1 # 不區分字母大小寫
log-bin=mysql-bin # 開啓二進制日誌
server-id=1 # 設置server-id
# 不同步哪些數據庫
binlog-ignore-db = mysql
binlog-ignore-db = test
binlog-ignore-db = information_schema
# 只同步哪些數據庫,除此之外,其他不同步
# binlog-do-db = game
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
配置完成之後,還要重啓一下數據庫:
service mysqld restart
現在執行第三步, 獲得主(master)數據庫二進制日誌文件名及位置,首先登陸數據庫:
[root@node2 ~]# mysql -u root -p
然後輸入以下命令獲取這些信息:
mysql> show master status;
正常情況下是輸出以下信息,其中File和Position都是我們在設置從(slave)數據庫的時候用到的:
+------------------+----------+--------------+-------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+-------------------------------+
| mysql-bin.000003 | 106 | | mysql,test,information_schema |
+------------------+----------+--------------+-------------------------------+
1 row in set (0.00 sec)
從(slave)數據庫配置:
- 配置唯一的server-id;
- 使用主(master)數據庫設置的用戶賬號讀取主(master)數據庫的bin二進制日誌;
- 啓用slave服務;
首先配置server-id,編輯/etc/my.cnf文件。在[mysqld]下加上下面一行代碼,這個server-id不要跟之前的主(master)數據庫服務器獲取其他數據庫一樣,要唯一的:
server-id=2 # 設置server-id,必須唯一
同樣要重啓一下數據庫:
service mysqld restart
然後登錄到數據庫,進行以下配置。首先是配置主(master)數據庫的IP地址,用戶命,登錄密碼,剛纔在主(master)數據庫中查到的bin二進制文件的名稱和所在的位置。
mysql> change master to
-> master_host='192.168.204.122',
-> master_user='root',
-> master_password='root',
-> master_log_file='mysql-bin.000003',
-> master_log_pos=106;
配置完成之後就啓動slave,命令如下:
mysql> start slave;
然後可以查看配置結果,使用以下命令查看:
mysql> show slave status\G;
正常情況下是輸出以下內容的:
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.204.122
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 106
Relay_Log_File: mysqld-relay-bin.000002
Relay_Log_Pos: 251
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 106
Relay_Log_Space: 407
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
1 row in set (0.00 sec)
ERROR:
No query specified
可以通過這些輸出信息查看配置信息是否正確,其中最重要的是以下這兩條信息,必須兩個都是Yse纔可以使用,這兩個就是從(slave)數據庫的兩個讀取和執行SQL語句的線程。
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
到這裏就已經配置完成了,我們接下來可以測試一下配置效果了。
測試配置¶
爲了方便測試,筆者使用NavicatForMySQL連接數據庫,讀者可以使用自己熟悉的連接工具,或者是直接在命令行上直接操作。
首先是連接主(master)數據庫:

在主(master)數據庫中創建一個yeyupiaoling數據庫:

並在這個數據庫中創建一張user表:

然後我們在這張表中添加以下數據:

然後連接從(slave)數據庫:

可以發現從(slave)數據庫中已經創建了一個yeyupiaoling數據庫,同時也有了一張user表,該表的數據庫都是一樣的。

從上面的測試來看,我們的數據是已經保證了主從數據一致了。也表命令了我門只要對主(master)數據庫進行寫入操作,從(slave)數據庫就會作相應的操作,保證主從(slave)數據庫數據一致。但我們對從(slave)數據庫進行寫入操作時,是不會對主(master)數據庫進行改動的,在實際的情況下也不應該對從(slave)數據庫進行寫入操作。筆者就不在這裏進行展示了,有興趣的讀者可以嘗試一下。
參考資料¶
- https://www.cnblogs.com/gl-developer/p/6170423.html
- https://blog.csdn.net/daicooper/article/details/79905660
- https://blog.csdn.net/darkangel1228/article/details/80004222
- https://blog.csdn.net/darkangel1228/article/details/80003967