一、MySQL主從復制的作用
1、數據熱備:作為后備數據庫,主數據庫服務器故障后,可切換到從數據庫繼續工作,避免數據丟失。
2、架構擴展:業務量越來越大,I/O訪問頻率過高,單機無法滿足,此時做多庫的存儲,降低磁盤I/O訪問的頻率,提高單個機器的I/O性能。
3、讀寫分離:使數據庫能支撐更大的並發。在報表中尤其重要。由於部分報表sql語句非常的慢,導致鎖表,影響前台服務。如果前台使用master,報表使用slave,那么報表sql將不會造成前台鎖,保證了前台速度。
二、MySQL主從復制的流程
1、主庫db的更新事件(update、insert、delete)被寫到binlog
2、從庫發起連接,連接到主庫
3、此時主庫創建一個binlog dump thread線程,把binlog的內容發送到從庫
4、從庫啟動之后,創建一個I/O線程,讀取主庫傳過來的binlog內容並寫入到relay log.
5、還會創建一個SQL線程,從relay log里面讀取內容,從Exec_Master_Log_Pos位置開始執行讀取到的更新事件,將更新內容寫入到slave的db
補充:由上述可知
對於每一個主從復制的連接,都有三個線程
1)inlog輸出線程:每當有從庫連接到主庫的時候,主庫都會創建一個線程然后發送binlog內容到從庫。
在從庫里,當復制開始的時候,從庫就會創建兩個線程進行處理:
2)從庫I/O線程:當START SLAVE語句在從庫開始執行之后,從庫創建一個I/O線程,該線程連接到主庫並請求主庫發送binlog里面的更新記錄到從庫上。從庫I/O線程讀取主庫的binlog輸出線程發送的更新並拷貝這些更新到本地文件,其中包括relay log文件。
3)從庫的SQL線程:從庫創建一個SQL線程,這個線程讀取從庫I/O線程寫到relay log的更新事件並執行。
三、MySQL主從同步環境部署
3.1、環境規划
安裝MySQL主從同步前,先分別安裝兩台單機版MySQL,參見:https://www.cnblogs.com/wuxinchun/p/15194008.html
主機 | 系統 | IP | 賬號 | 密碼 | 服務 |
Master | Centos7.4 | 10.3.104.52 | master | 123456 | MySQL5.7 |
Slave | Centos7.4 | 10.3.104.56 | slave | 123456 | MySQL5.7 |
1、master數據庫的my.cnf配置(Master主服務器上操作)
[root@docker01 ~]# vim /etc/my.cnf #數據庫唯一ID,主從的標識號絕對不能重復。 server-id=1 #開啟bin-log,並指定文件目錄和文件名前綴 log-bin=mysql-bin #需要同步的數據庫。如果是多個同步庫,就以此格式另寫幾行即可。如果不指明對某個具體庫同步,就去掉此行,表示同步所有庫(除了ignore忽略的庫) #binlog-do-db=kevin #不同步mysql系統數據庫。如果是多個不同步庫,就以此格式另寫幾行;也可以在一行,中間逗號隔開 binlog-ignore-db = mysql,information_schema #每次寫入時都將binlog與硬盤同步 sync_binlog = 1 #binlog日志格式,mysql默認采用statement,建議使用mixed binlog_format = MIXED #binlog日志文件 log-bin =/var/lib/mysql/mysql-bin.log #binlog過期清理時間 expire_logs_days = 7 #binlog每個日志文件大小 max_binlog_size = 100m #binlog緩存大小 binlog_cache_size = 4m #最大binlog緩存大小 max_binlog_cache_size = 512m
2、slave數據庫的my.cnf配置(Slave從服務器上操作)
[root@docker02 ~]# vim /etc/my.cnf #數據庫唯一ID,主從的標識號絕對不能重復。 server-id=2 #開啟bin-log,並指定文件目錄和文件名前綴 log-bin=mysql-bin #需要同步的數據庫。如果是多個同步庫,就以此格式另寫幾行即可。如果不指明對某個具體庫同步,就去掉此行,表示同步所有庫(除了ignore忽略的庫) #binlog-do-db=kevin #不同步mysql系統數據庫。如果是多個不同步庫,就以此格式另寫幾行;也可以在一行,中間逗號隔開 binlog-ignore-db = mysql,information_schema #每次寫入時都將binlog與硬盤同步 sync_binlog = 1 #binlog日志格式,mysql默認采用statement,建議使用mixed binlog_format = MIXED #binlog日志文件 log-bin =/var/lib/mysql/mysql-bin.log #binlog過期清理時間 expire_logs_days = 7 #binlog每個日志文件大小 max_binlog_size = 100m #binlog緩存大小 binlog_cache_size = 4m #最大binlog緩存大小 max_binlog_cache_size = 512m
3、master創建用於slave機器獲取master機器上binlog文件的賬號(Master主服務器上操作)
mysql> grant replication slave,replication client on *.* to slave@'10.3.104.56' identified by "123456"; //IP為slave地址 Query OK, 0 rows affected (0.02 sec) mysql> flush privileges; Query OK, 0 rows affected (0.00 sec)
4、slave庫同步master庫的命令如下(即不需要跟master_log_file 和 master_log_pos=120,slave服務器上操作):
mysql> stop slave; mysql> change master to master_host = '10.3.104.52', master_port = 3306, master_user ='slave', master_password ='123456'; mysql> start slave; mysql> show slave status \G; Slave_IO_Running: Yes Slave_SQL_Running: Yes
注:上述已完成單向主從同步
3.2、驗證單向數據同步性
1)在master上創建表並插入數據
mysql> create database test; Query OK, 1 row affected (0.00 sec) mysql> use test; Database changed mysql> create table testtable(id int,name varchar(20)); Query OK, 0 rows affected (0.02 sec) mysql> insert into testtable values (1,'zhangsan'); Query OK, 1 row affected (0.01 sec) mysql> select * from testtable; +------+----------+ | id | name | +------+----------+ | 1 | zhangsan | +------+----------+ 1 row in set (0.00 sec)
2)slave庫檢查數據
mysql> select * from test.testtable; +------+----------+ | id | name | +------+----------+ | 1 | zhangsan | +------+----------+ 1 row in set (0.00 sec)
注:說明數據已經同步到slave
3.3、雙向同步配置驗證
1)slave創建用於master機器獲取slave機器上binlog文件的賬號(slave服務器上操作)
mysql> grant replication slave,replication client on *.* to master@'10.3.104.52' identified by "123456"; //IP為master地址 Query OK, 0 rows affected (0.02 sec) mysql> flush privileges; Query OK, 0 rows affected (0.00 sec)
2)master庫同步slave庫的命令如下(master服務器上操作)
mysql> stop slave; mysql> change master to master_host = '10.3.104.56', master_port = 3306, master_user ='master', master_password ='123456'; mysql> start slave; mysql> show slave status \G; Slave_IO_Running: Yes Slave_SQL_Running: Yes
注:上述雙向同步已配置完成
1)如果單向同步就關閉另一端stop slave;
2)如果雙向同步在兩個節點分別執行start slave
補充:mysql主從同步延時分析
mysql的主從復制都是單線程的操作,主庫對所有DDL和DML產生的日志寫進binlog,由於binlog是順序寫,所以效率很高,slave的sql thread線程將主庫的DDL和DML操作事件在slave中重放。DML和DDL的IO操作是隨機的,不是順序,所以成本要高很多,另一方面,由於sql thread也是單線程的,當主庫的並發較高時,產生的DML數量超過slave的SQL thread所能處理的速度,或者當slave中有大型query語句產生了鎖等待,那么延時就產生了。
解決方案:
1.業務的持久化層的實現采用分庫架構,mysql服務可平行擴展,分散壓力。
2.單個庫讀寫分離,一主多從,主寫從讀,分散壓力。這樣從庫壓力比主庫高,保護主庫。
3.服務的基礎架構在業務和mysql之間加入memcache或者redis的cache層。降低mysql的讀壓力。
4.不同業務的mysql物理上放在不同機器,分散壓力。
5.使用比主庫更好的硬件設備作為slave,mysql壓力小,延遲自然會變小。
6.使用更加強勁的硬件設備