MySql主從複製實現原理及配置
資料庫讀寫分離對於大型系統或者訪問量很高的網際網路應用來說,是必不可少的一個重要功能。對於MySQL來說,標準的讀寫分離是主從模式,一個寫節點Master後面跟著多個讀節點,讀節點的數量取決於系統的壓力,通常是1-3個讀節點的配置。而一般的讀寫分離中介軟體,例如Mycat的讀寫分離和自動切換機制,需要mysql的主從複製機制配合。
主從配置需要注意的地方
1、主DB server和從DB server資料庫的版本一致
2、主DB server和從DB server資料庫資料名稱一致
3、主DB server開啟二進位制日誌,主DB server和從DB server的server_id都必須唯一MySQL主伺服器配置
第一步:修改my.conf檔案:
在[mysqld]段下新增:
binlog-ignore-db=mysql #啟用二進位制日誌 log-bin=mysql-bin //二進位制日誌的格式,有三種:statement/row/mixed binlog_format=row #主伺服器唯一ID,一般取IP最後一段 server-id=82
第二步:重啟mysql服務
service mysql restart
第三步:建立帳戶並授權slave
mysql>GRANT FILE ON *.* TO 'slave'@'%' IDENTIFIED BY 'slavepw';
mysql>GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* to 'slave'@'%' identified by 'slavepw';
一般不用root帳號,“%”表示所有客戶端都可能連,只要帳號,密碼正確,此處可用具體客戶端IP代替,如192.168.145.226,加強安全。
重新整理許可權
mysql> FLUSH PRIVILEGES;
第四步:查詢master的狀態
mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 881 | | mysql | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec)
MySQL從伺服器配置
第一步:修改my.conf檔案
[mysqld]#從伺服器唯一ID,一般取IP最後一段server-id=83
第二步:配置從伺服器
mysql>change master to master_host='192.168.11.82',master_port=3306,master_user='slave',master_password='slavepw',master_log_file='mysql-bin.000001',master_log_pos=881;
注意語句中間不要斷開,master_port為mysql伺服器埠號(無引號),master_user為執行同步操作的資料庫賬戶,“881”無單引號(此處的881就是show master status 中看到的position的值,這裡的mysql-bin.000001就是file對應的值)。
第三步:啟動從伺服器複製功能
mysql>start slave;
第四步:檢查從伺服器複製功能狀態:
mysql> show slave status;
Slave_IO_Running: Yes //此狀態必須YES
Slave_SQL_Running: Yes //此狀態必須YES
注:Slave_IO及Slave_SQL程序必須正常執行,即YES狀態,否則都是錯誤的狀態(如:其中一個NO均屬錯誤)。
進行驗證
在主節點上建立表、插入資料,發現從節點也建立表並插入資料。
MySQL 主從複製原理的是啥?
主庫將變更寫入 binlog 日誌,然後從庫連線到主庫之後,從庫有一個 IO 執行緒,將主庫的 binlog 日誌拷貝到自己本地,寫入一個 relay 中繼日誌中。接著從庫中有一個 SQL 執行緒會從中繼日誌讀取 binlog,然後執行 binlog 日誌中的內容,也就是在自己本地再次執行一遍 SQL,這樣就可以保證自己跟主庫的資料是一樣的。
這裡有一個非常重要的一點,就是從庫同步主庫資料的過程是序列化的,也就是說主庫上並行的操作,在從庫上會序列執行。所以這就是一個非常重要的點了,由於從庫從主庫拷貝日誌以及序列執行 SQL 的特點,在高併發場景下,從庫的資料一定會比主庫慢一些,是有延時的。所以經常出現,剛寫入主庫的資料可能是讀不到的,要過幾十毫秒,甚至幾百毫秒才能讀取到。
而且這裡還有另外一個問題,就是如果主庫突然宕機,然後恰好資料還沒同步到從庫,那麼有些資料可能在從庫上是沒有的,有些資料可能就丟失了。
所以 MySQL 實際上在這一塊有兩個機制,一個是半同步複製,用來解決主庫資料丟失問題;一個是並行複製,用來解決主從同步延時問題。
這個所謂半同步複製,也叫semi-sync
複製,指的就是主庫寫入 binlog 日誌之後,就會將強制此時立即將資料同步到從庫,從庫將日誌寫入自己本地的 relay log 之後,接著會返回一個 ack 給主庫,主庫接收到至少一個從庫的 ack 之後才會認為寫操作完成了。
所謂並行複製,指的是從庫開啟多個執行緒,並行讀取 relay log 中不同庫的日誌,然後並行重放不同庫的日誌,這是庫級別的並行。
MySQL 主從同步延時問題
以前線上確實處理過因為主從同步延時問題而導致的線上的 bug,屬於小型的生產事故。
是這個麼場景。有個同學是這樣寫程式碼邏輯的。先插入一條資料,再把它查出來,然後更新這條資料。在生產環境高峰期,寫併發達到了 2000/s,這個時候,主從複製延時大概是在小几十毫秒。線上會發現,每天總有那麼一些資料,我們期望更新一些重要的資料狀態,但在高峰期時候卻沒更新。使用者跟客服反饋,而客服就會反饋給我們。
我們通過 MySQL 命令:
show status
檢視Seconds_Behind_Master
,可以看到從庫複製主庫的資料落後了幾 ms。
一般來說,如果主從延遲較為嚴重,有以下解決方案:
分庫,將一個主庫拆分為多個主庫,每個主庫的寫併發就減少了幾倍,此時主從延遲可以忽略不計。開啟 MySQL 支援的並行複製,多個庫並行複製。如果說某個庫的寫入併發就是特別高,單庫寫併發達到了 2000/s,並行複製還是沒意義。重寫程式碼,寫程式碼的同學,要慎重,插入資料時立馬查詢可能查不到。如果確實是存在必須先插入,立馬要求就查詢到,然後立馬就要反過來執行一些操作,對這個查詢設定直連主庫。不推薦這種方法,你要是這麼搞,讀寫分離的意義就喪失了。開啟並行複製
開啟多執行緒複製,預設關鍵的引數有兩個:
mysql> show variables like 'slave_parallel_%'; +------------------------+----------+ | Variable_name | Value | +------------------------+----------+ | slave_parallel_type | DATABASE | | slave_parallel_workers | 0 | +------------------------+----------+ 2 rows in set (0.00 sec)
slave-parallel-type 預設值為database
slave-parallel-workers 預設值為0
開啟:
mysql> stop slave sql_thread; Query OK,0 rows affected (0.05 sec) mysql> set global slave_parallel_type='LOGICAL_CLOCK'; Query OK,0 rows affected (0.00 sec) mysql> set global slave_parallel_workers=4; Query OK,0 rows affected (0.00 sec) mysql> start slave sql_thread; Query OK,0 rows affected (0.07 sec)
參考資料:
https://www.jianshu.com/p/3932551e0221
https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/mysql-read-write-separation.md
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。