前言

我們用的在這篇文章《在CentOS上使用Nginx和Tomcat搭建高可用高併發網站》使用的只有一個MySQL數據庫。

  • 從安全角度來說這是非常不安全的,比如這個數據庫服務器磁盤突然損壞了,裏面的數據全部丟失了。這種情況如果一開始只是部署一個數據庫的話就非常危險了,這表明我們要丟失全部數據,而數據對網站來說是最最重要的,所以我們要保證數據的安全。
  • 從性能上來說,我們在《CentOS下安裝和使用Mycat實現分佈式數據庫》這篇文章中介紹了分佈式數據庫,性能雖然比單個數據庫的性能要好。但是當使用分佈式數據庫時,數據量還是很大,在查詢數據時,可能會變得非常慢,導致鎖表,一旦鎖表就無法寫入數據,就會影響其他用戶的寫入數據的操做。所以就需要讀寫分離,主(master)數據庫負責寫入數據,從(slave)數據庫負責查詢數據,就算從(slave)數據庫在查詢數據時出現了鎖表,也不會影響到主(master)數據庫的的寫入操作,最多也是從(slave)數據庫的數據更新的慢一些。基於這種情況,就出現了主從複製這個技術。

主從複製: 就是有兩個數據庫服務器,一個是主(master)數據庫服務器,另一個是從(slave)數據庫服務器。當主(master)數據庫有數據寫入,包括插入、刪除、修改,都會在從(slave)數據庫上操作一次。這樣的操作下,主從(slave)數據庫的數據都是一樣的,就相當於時刻在做數據備份,就算主(master)數據庫的數據全部丟失了,還有從(slave)數據庫的數據,我們就可以把從(slave)數據庫的數據導出來進行數據恢復。

主從複製原理主要有三個線程不斷在工作:

  1. 主(master)數據庫啓動bin二進制日誌,這樣會有一個Dump線程,這個線程是把主(master)數據庫的寫入操作都會記錄到這個bin的二進制文件中。
  2. 然後從(slave)數據庫會啓動一個I/O線程,這個線程主要是把主(master)數據庫的bin二進制文件讀取到本地,並寫入到中繼日誌(Relay log)文件中。
  3. 最後從(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)數據庫進行寫入操作。筆者就不在這裏進行展示了,有興趣的讀者可以嘗試一下。

參考資料

  1. https://www.cnblogs.com/gl-developer/p/6170423.html
  2. https://blog.csdn.net/daicooper/article/details/79905660
  3. https://blog.csdn.net/darkangel1228/article/details/80004222
  4. https://blog.csdn.net/darkangel1228/article/details/80003967
小夜