基於 MySQL 主從模式搭建上萬併發的系統架構

來源:html

https://my.oschina.net/u/4205711/blog/3104493mysql


1、主從複製基礎概念linux

在瞭解主從複製以前必需要了解的就是數據庫的二進制日誌(binlog),主從複製架構大多基於二進制日誌進行。

1.1 二進制日誌管理說明sql

二進制日誌在哪?如何設置位置和命名?shell

在my.cnf文件中使用 log-bin = 指定;命名規則爲 mysql-bin.000000 (後爲6位數字)數據庫

二進制日誌位置安全

mysql> show variables like '%log_bin%' ;
+---------------------------------+-----------------------------------------+
| Variable_name | Value |
+---------------------------------+-----------------------------------------+
| log_bin | ON |
| log_bin_basename | /application/mysql/data/mysql-bin |
| log_bin_index | /application/mysql/data/mysql-bin.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+-----------------------------------------+
6 rows in set (0.06 sec)

日誌命名:服務器

mysql> show binary logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 2979 |
| mysql-bin.000002 | 120 |
+------------------+-----------+
2 rows in set (0.00 sec)

二進制日誌記錄什麼?二進制日誌中記錄的是一個個完成的事件網絡

二進制日誌格式是怎樣的?推薦使用row格式架構

查看當前使用的日誌格式:

mysql> show variables like '%format%';
+--------------------------+-------------------+
| Variable_name | Value |
+--------------------------+-------------------+
| binlog_format | ROW |
| date_format | %Y-%m-%d |
| datetime_format | %Y-%m-%d %H:%i:%s |
| default_week_format | 0 |
| innodb_file_format | Antelope |
| innodb_file_format_check | ON |
| innodb_file_format_max | Antelope |
| time_format | %H:%i:%s |
+--------------------------+-------------------+
8 rows in set (0.00 sec)

二進制日誌如何滾動?每次重啓都會刷新日誌,也能夠經過命令進行刷新 reset master;

二進制日誌用來幹嗎?備份恢復,起始點的備份恢復

二進制日誌的操做命令?查看都有哪些二進制日誌

mysql> show binary logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 2979 |
| mysql-bin.000002 | 167 |
| mysql-bin.000003 | 120 |
+------------------+-----------+
3 rows in set (0.00 sec)

查看當前使用的二進制日誌文件:

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 120 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

binlog相關詳情參照:

http://www.cnblogs.com/clsn/p/8087678.html#_label6

1.2 mysql傳統備份方式和缺陷

  1. 二進制日誌備份

  2. mysqldump

  3. 必須有數據庫服務器完成邏輯工做,須要更多地cpu週期

  4. 邏輯備份還原速度慢:須要MySQL加載和解釋語句、轉化存儲格式、重建引擎

  5. xtrabackup

  6. 文件大

  7. 不老是能夠跨平臺、操做系統和MySQL版本

1.3 MySQL主從複製能爲咱們作什麼

  • 高可用

  • 輔助備份

  • 分擔負載

2、MySQL主從複製介紹

2.1 複製技術

做用:

  • 保證數據安全(異機實時備份)

  • 保證服務持續運行(宕機接管)

主從複製實現基本原理

  • 自帶功能,複製是 MySQL 的一項功能,容許服務器將更改從一個實例複製到另外一個實例。

  • 主服務器將全部數據和結構更改記錄到二進制日誌中。

  • 從屬服務器從主服務器請求該二進制日誌並在本地應用其內容。即經過把主庫的binlog傳送到從庫,重新解析應用到從庫。

2.2 複製架構

mysql複製的應用常見場景:

應用場景1:從服務器做爲主服務器的實時數據備份

應用場景2:主從服務器實現讀寫分離,從服務器實現負載均衡

應用場景3:把多個從服務器根據業務重要性進行拆分訪問

傳統的 MySQL複製提供了一種簡單的主–從複製方法,有一個主,以及一個或多個從。

主節點執行和提交事務,而後將它們(異步地)發送到從節點,以從新執行(在基於語句的複製中)或應用(在基於行的複製中)。

這是一個 shared-nothing 的系統,默認狀況下全部 server 成員都有一個完整的數據副本。

 

640

(圖)MySQL 異步複製

還有一個半同步複製,它在協議中添加了一個同步步驟。

這意味着主節點在提交時須要等待從節點確認它已經接收到事務。只有這樣,主節點才能繼續提交操做。

 

640

(圖)MySQL 異步複製

在上面的兩個圖片中,能夠看到傳統異步 MySQL 複製協議(以及半同步)的圖形展現。

藍色箭頭表示在不一樣 server 之間或者 server 與 client 應用之間的信息交互。

2.3 MySQL主從複製原理介紹

複製過程:

  • 開啓binlog日誌,經過把主庫的binlog傳送到從庫,重新解析應用到從庫。

  • 複製須要3個線程(dump、io、sql)完成,5.6從庫多個sql。

  • 複製是異步的過程。主從複製是異步的邏輯的SQL語句級的複製。

複製前提:

  • 主服務期必定要打開二進制日誌

  • 必須兩臺服務器(或者是多個實例)

  • 從服務器須要一次數據初始化

  • 若是主從服務器都是新搭建的話,能夠不作初始化

  • 若是主服務器已經運行了很長時間,能夠經過備份將主庫數據恢復到從庫

  • 主庫必需要有對從庫複製請求的用戶。

  • 從庫須要有relay-log設置,存放從主庫傳送過來的二進制日誌:

  • show variables like '%relay%';

  • 在第一次的時候,從庫須要change master to 去鏈接主庫。

  • change master信息須要存放到master.info中 :

  • show variables like '%master_info%';

  • 從庫怎麼知道,主庫發生了新的變化?經過relay-log.info記錄的已經應用過的relay-log信息。

  • 在複製過程當中涉及到的線程

  • 從庫會開啓一個IO thread(線程),負責鏈接主庫,請求binlog,接收binlog並寫入relay-log。

  • 從庫會開啓一個SQL thread(線程),負責執行relay-log中的事件。

  • 主庫會開啓一個dump thrad(線程),負責響應從IO thread的請求。

主從怎麼實現的?

  • 經過二進制日誌

  • 至少兩臺(主、從)

  • 主服務器的二進制日誌「拿」到從服務器上再運行一遍。

  • 經過網絡鏈接兩臺機器,通常都會出現延遲的狀態。也能夠說是異步的。

640

 

2.4 執行原理--第一次開啓主從過程

  • 從庫經過手工執行change master to 語句鏈接主庫,提供了鏈接的用戶一切條件:

  • (user、password、port、ip)

  • 而且讓從庫知道,二進制日誌的起點位置(file名 position號)

  • start slave

  • 從庫的IO和主庫的dump線程創建鏈接

  • 從庫根據change master to 語句提供的file名和position號,IO線程向主庫發起binlog的請求

  • 主庫dump線程根據從庫的請求,將本地binlog以events的方式發給從庫IO線程

  • 從庫IO線程接收binlog evnets,並存放到本地relay-log中,傳送過來的信息,會記錄到master.info中。

  • 從庫SQL線程應用relay-log,而且把應用過的記錄到relay-log.info,默認狀況下,已經應用過的relay會自動被清理purge。

到此爲止,一次主從複製就完成

一旦主從運行起來:就不須要手工執行change master to,由於信息都會被存放到master.info(user、password、port、ip,上次獲取過的binlog信息file和position)中。

詳細的mysql replication 過程

 

640

 

3、 主從搭建配置

本次主從搭建使用mysql多實例進行實驗。多實例配置參考文檔進行配置:

http://www.cnblogs.com/clsn/p/8038964.html#_label8

3.1 多實例數據庫slave配置

系統環境說明:

[root@db02 ~]# cat /etc/redhat-release
CentOS release 6.9 (Final)
[root@db02 ~]# uname -r
2.6.32-696.el6.x86_64
[root@db02 ~]# /etc/init.d/iptables status
iptables: Firewall is not running. # 注意:務必關閉防火牆(iptables selinux)
[root@db02 ~]# getenforce
Disabled
[root@db02 ~]# mysql --version
mysql Ver 14.14 Distrib 5.6.36, for Linux (x86_64) using EditLine wrapper

一、啓動多實例數據庫

[root@db02 ~]# /data/3306/mysql start
Starting MySQL...
[root@db02 ~]# /data/3307/mysql start
Starting MySQL...

二、配置文件說明:

master 配置文件說明:

[root@db02 ~]# cat /data/3306/my.cnf
[client]
port = 3306
socket = /data/3306/mysql.sock
[mysqld]
user = mysql
port = 3306
socket = /data/3306/mysql.sock
basedir = /application/mysql
datadir = /data/3306/data
log-bin = /data/3306/mysql-bin
server-id = 6 # server id 不能相同
skip_name_resolve = 0 # 跳過域名解析參數
[mysqld_safe]
log-error=/data/3306/mysql_3306.err
pid-file=/data/3306/mysqld.pid

slave 配置文件說明:

[root@db02 ~]# cat /data/3307/my.cnf
[client]
port = 3307
socket = /data/3307/mysql.sock
[mysqld]
user = mysql
port = 3307
socket = /data/3307/mysql.sock
basedir = /application/mysql
datadir = /data/3307/data
log-bin = /data/3307/mysql-bin
server-id = 7 # server id 不能相同
skip_name_resolve = 0 # 跳過域名解析參數
read_only = 1 # 從庫只讀 (非root用戶 )
[mysqld_safe]
log-error=/data/3307/mysql_3307.err
pid-file=/data/3307/mysqld.pid

三、在主庫建立複製用戶

登錄到主數據庫中:

mysql -uroot -p123 -S /data/3306/mysql.sock

建立受權用戶,注意是slave用戶。

grant replication slave on *.* to repl@'10.0.0.%' identified by '123';

四、初始化從庫數據

備份主庫當前數據

mysqldump -uroot -p123 -A -B -F --master-data=2 -S /data/3306/mysql.sock >/tmp/full.sql

部分參數說明:

  • -F 刷新二進制日誌

  • --master-data [=#]這會致使二進制日誌的位置和文件名被追加到輸出中。若是等於1,則將其打印爲CHANGE MASTER命令; 若是等於2,那麼該命令將以註釋符號爲前綴。

到從庫進行恢復

mysql -uroot -p123 -S /data/3307/mysql.sock

恢復備份的數據

set sql_log_bin=0;
source /tmp/full.sql

五、開啓從庫複製

查看備份的當前使用的文件及POS號

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000012 | 120 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

登入數據庫,進行slave配置。

mysql -uroot -p123 -S /data/3307/mysql.sock
CHANGE MASTER TO
MASTER_HOST='10.0.0.52',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000012',
MASTER_LOG_POS=120;
start slave; # 啓動從庫複製

該配置想關說明能夠經過 help 得到。

mysql> help CHANGE MASTER TO
CHANGE MASTER TO
MASTER_HOST='master2.mycompany.com',
MASTER_USER='replication',
MASTER_PASSWORD='bigs3cret',
MASTER_PORT=3306,
MASTER_LOG_FILE='master2-bin.001',
MASTER_LOG_POS=4,
MASTER_CONNECT_RETRY=10;

3.2 測試主從同步

查看slave庫的狀態,主要查看:

Slave_IO_Running與Slave_SQL_Running是否都爲Yes

主庫進行操做,在從庫驗證

[root@db02 ~]# mysql -uroot -p123 -S /data/3306/mysql.sock
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
+--------------------+
4 rows in set (0.00 sec)
mysql> create database clsn;
Query OK, 1 row affected (0.00 sec)

在從庫上能夠看到該數據庫已建立

[root@db02 ~]# mysql -uroot -p123 -S /data/3307/mysql.sock
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| clsn |
| mysql |
| performance_schema |
| test |
+--------------------+
5 rows in set (0.00 sec)

至此mysql主從複製就搭建完成

3.3 忘記數據庫密碼?

shell> /application/mysql/bin/mysqld_safe --defaults-file=/data/3306/my.cnf --skip-grant-tables --skip-networking &
mysql> update user set password=password('123') where user='root' and host='localhost';
mysql> flush privileges;

3.4 主從複製狀態失敗的緣由?

Last_IO_Error: error reconnecting to master 'repl@10.0.0.52:3306' - retry-time: 60 retries: 1

緣由:

  • 主機沒啓動,或者宕機,檢查主庫的狀態。

  • 網絡通訊問題,使用ping命令進行檢查;或使用mysql命令進行shell端登錄測試

  • 防火牆,selinux(務必檢查)

  • 複製用戶和密碼、端口號、地址有問題,使用mysql命令進行shell端登錄測試。

  • mysql自動解析,會將鏈接的IP解析成主機名(skip-name-resolve = 0)寫入my.cnf文件便可。

  • 從庫IO異常關閉,經過show slave status \G 進行查看。

4、MySQL主從複製常見問題

4.1 從庫binlog落後主庫binlog?

從庫記錄的已經主庫已經給我傳送的binlog事件的座標,通常在繁忙的生產環境下會落後於主庫

show master status\G --- 主
show slave status \G --- 從
Master_Log_File: mysql-bin.000007
Read_Master_Log_Pos: 729

落後太遠的緣由:

  • 硬件條件有關的,機器磁盤IO性能不足。

  • 主要仍是網絡問題,網絡傳輸的性能。

  • 主庫存放二進制日誌的存儲性能過低,建議binlog日誌存咋SSD中。

  • 主庫DUMP線程太繁忙,主要發生在一主多從的環境下。

  • 從庫IO線程太忙

  • 人爲控制(delay節點、延時節點 )

4.2 主庫update,從庫遲遲的沒有更新

特殊狀況日誌已經傳過來了,數據並無同步

通常狀況:

  • 沒開啓SQL線程

  • 傳的東西有問題(你要作的事情,我提早已經作了,不想重複作了,而後他就死了)

  • SQL線程忙

  • 人爲控制了【delay(從庫)節點、延時節點,通常生產設置爲3-6小時之間,能夠保證過去3-6小時之間的誤操做,能夠避免】

4.3 主從複製延時配置(從庫配置)

中止從庫複製

mysql>stop slave;
Query OK, 0 rows affected (0.01 sec)

修改延時參數,MASTER_DELAY,單位位S (秒)。

mysql>CHANGE MASTER TO MASTER_DELAY = 30;
Query OK, 0 rows affected (0.07 sec)

啓動從庫複製

mysql>start slave;
Query OK, 0 rows affected (0.07 sec)

查看配置是否生效

mysql> show slave status \G
……
SQL_Delay: 30

4.4 從庫安全配置(其餘用戶只讀)

修改my.cnf配置文件,添加只讀參數

read_only = 1 ====> 控制普通用戶
innodb_read_only = 1 ====> 控制root用戶,正常狀況不要加

添加完成後重啓數據庫

mysql> show variables like '%read_only%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| innodb_read_only | OFF |
| read_only | ON |
| tx_read_only | OFF |
+------------------+-------+
3 rows in set (0.00 sec)

延時從庫: delay節點、延時節點

4.5 主從複製故障及解決(跳過錯誤)

命令行設置

stop slave; #<==臨時中止同步開關。
set global sql_slave_skip_counter = 1 ; #<==將同步指針向下移動一個,若是屢次不一樣步,能夠重複操做。
start slave;

在配置文件修改,設置要跳過的pos

/etc/my.cnf
slave-skip-errors = 1032,1062,1007

在mysql中能夠跳過某些錯誤,可是最好的解決辦法,從新搭建主從複製。

4.6 延時節點概念 --> SQL線程延時?

Last_SQL_Errno: 0
Last_SQL_Error:

緣由:

  • 主庫作操做的對象,在從庫不存在

  • 主庫作操做的對象屬性不一致

  • 主庫作操做的對象,從庫已經存在

……

4.7 Slave_*_Running:?

  • Slave_IO_Running I/O 線程正在運行、未運行仍是正在運行但還沒有鏈接到主服務器。可能值分別爲Yes、No 或 Connecting。

  • Slave_SQL_Running SQL線程當前正在運行、未運行,可能值分別爲Yes、No

  • 主服務器日誌座標:Master_Log_File 和 Read_Master_Log_Pos 標識主服務器二進制日誌中 I/O 線程已經傳輸的最近事件的座標。

  • 若是Master_Log_File和Read_Master_Log_Pos 的值遠遠落後於主服務器上的那些值,這表示主服務器與從屬服務器之間事件的網絡傳輸可能存在延遲。

4.8 中繼日誌座標

Relay_Log_File 和 Relay_Log_Pos 列標識從屬服務器中繼日誌中 SQL 線程已經執行的最近事件的座標。

這些座標對應於 Relay_Master_Log_File 和 Exec_Master_Log_Pos 列標識的主服務器二進制日誌中的座標。

若是 Relay_Master_Log_File 和 Exec_Master_Log_Pos 列的輸出遠遠落後於 Master_Log_File 和Read_Master_Log_Pos 列(表示 I/O 線程的座標)

這表示 SQL 線程(而不是 I/O 線程)中存在延遲。即,它表示複製日誌事件快於執行這些事件。

4.9 單一主從須要改變的地方

從庫的做用

一、至關於實時備份

二、使用從庫備份

三、一主多從應對讀多的業務需求

若是,從庫只作備份服務器用,那麼主庫的壓力會不減反增。由於,全部的業務都在主庫實現,讀和寫,dump線程讀取並投遞binlog

解決方案:

  • 可不能夠挪走一部分讀業務到從庫,讀寫分離

  • 一主多從應對讀多的業務需求,一旦發展成這個架構,dump線程投遞binlog的壓力更大

  • 多級主從,採用中間庫緩解主庫dump的壓力,會出現中間庫瓶頸的問題,選擇blackhole引擎,看性能與安全的權衡

  • 雙主模型:緩解,數據一致性難保證

  • 環狀複製


【推薦閱讀

[技術]:分佈式 RPC 框架性能大比拼

[技術]:咱們公司使用了 6 年的分佈式鎖,非常牛逼啊!

[技術]:細思極恐 - 你真的會寫Java嗎

[技術]:提高10倍生產力:IDEA遠程一鍵部署SpringBoot到Docker

[技術]:用了這麼久 IDEA ,你居然不知道有個功能叫自動補全!


640?wx_fmt=jpeg

相關文章
相關標籤/搜索