MySQL雙主(主主)架構方案

在企業中,數據庫高可用一直是企業的重中之重,中小企業不少都是使用mysql主從方案,一主多從,讀寫分離等,可是單主存在單點故障,從庫切換成主庫須要做改動。所以,若是是雙主或者多主,就會增長mysql入口,增長高可用。不過多主須要考慮自增加ID問題,這個須要特別設置配置文件,好比雙主,可使用奇偶,總之,主之間設置自增加ID相互不衝突就能完美解決自增加ID衝突問題。mysql

主從同步複製原理

在開始以前,咱們先來了解主從同步複製原理。c++

複製分紅三步:程序員

1. master將改變記錄到二進制日誌(binary log)中(這些記錄叫作二進制日誌事件,binary log events);sql

2. slave將master的binary log events拷貝到它的中繼日誌(relay log);數據庫

3. slave重作中繼日誌中的事件,將改變反映它本身的數據。bootstrap

下圖描述了這一過程:緩存

Java架構師筆記-MySQL雙主(主主)架構方案

 

該過程的第一部分就是master記錄二進制日誌。在每一個事務更新數據完成以前,master在二日誌記錄這些改變。MySQL將事務串行的寫入二進制日誌,即便事務中的語句都是交叉執行的。在事件寫入二進制日誌完成後,master通知存儲引擎提交事務。服務器

下一步就是slave將master的binary log拷貝到它本身的中繼日誌。首先,slave開始一個工做線程——I/O線程。I/O線程在master上打開一個普通的鏈接,而後開始binlog dump process。Binlog dump process從master的二進制日誌中讀取事件,若是已經跟上master,它會睡眠並等待master產生新的事件。I/O線程將這些事件寫入中繼日誌。多線程

SQL slave thread處理該過程的最後一步。SQL線程從中繼日誌讀取事件,更新slave的數據,使其與master中的數據一致。只要該線程與I/O線程保持一致,中繼日誌一般會位於OS的緩存中,因此中繼日誌的開銷很小。架構

此外,在master中也有一個工做線程:和其它MySQL的鏈接同樣,slave在master中打開一個鏈接也會使得master開始一個線程。

MySQL5.6之前的版本複製過程有一個很重要的限制——複製在slave上是串行化的,也就是說master上的並行更新操做不能在slave上並行操做。 MySQL5.6版本參數slave-parallel-workers=1 表示啓用多線程功能。

MySQL5.6開始,增長了一個新特性,是加入了全局事務 ID (GTID) 來強化數據庫的主備一致性,故障恢復,以及容錯能力。

MySQL雙主(主主)架構方案思路是:

1.兩臺mysql均可讀寫,互爲主備,默認只使用一臺(masterA)負責數據的寫入,另外一臺(masterB)備用;

2.masterA是masterB的主庫,masterB又是masterA的主庫,它們互爲主從;

3.兩臺主庫之間作高可用,能夠採用keepalived等方案(使用VIP對外提供服務);

4.全部提供服務的從服務器與masterB進行主從同步(雙主多從);

5.建議採用高可用策略的時候,masterA或masterB均不因宕機恢復後而搶佔VIP(非搶佔模式);

這樣作能夠在必定程度上保證主庫的高可用,在一臺主庫down掉以後,能夠在極短的時間內切換到另外一臺主庫上(儘量減小主庫宕機對業務形成的影響),減小了主從同步給線上主庫帶來的壓力;

可是也有幾個不足的地方:

1.masterB可能會一直處於空閒狀態(能夠用它當從庫,負責部分查詢);

2.主庫後面提供服務的從庫要等masterB先同步完了數據後才能去masterB上去同步數據,這樣可能會形成必定程度的同步延時;

架構的簡易圖以下:

Java架構師筆記-MySQL雙主(主主)架構方案

 

主主環境(這裏只介紹2臺主的配置方案):

1.CentOS 6.8 64位 2臺:masterA(192.168.10.11),masterB(192.168.10.12)

2.官方Mysql5.6版本

搭建過程:

1.安裝MySQL服務(建議源碼安裝)

1.1 yum安裝依賴包

yum -y install make gcc gcc-c++ ncurses-devel bison openssl-devel

1.2 添加MySQL所須要的用戶和組

groupadd -g 27 mysql
adduser -u 27 -g mysql -s /sbin/nologin mysql

1.3 下載MySQL源碼包

mkdir -p /data/packages/src
cd /data/packages/
wget http://distfiles.macports.org/cmake/cmake-3.2.3.tar.gz
wget http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.34.tar.gz

1.4 建立mysql數據目錄

mkdir -p /usr/local/mysql/data

1.5 解壓編譯安裝cmake、MySQL

cd /data/packages/src
tar -zxvf ../cmake-3.2.3.tar.gz
cd cmake-3.2.3/
./bootstrap
gmake
make install
cd ../
tar xf mysql-5.6.34.tar.gz
cd mysql-5.6.34
cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DSYSCONFDIR=/etc
-DWITH_SSL=bundled -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci
-DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_MYISAM_STORAGE_ENGINE=1
-DMYSQL_TCP_PORT=3306 -DMYSQL_UNIX_ADDR=/tmp/mysql.sock
-DMYSQL_DATADIR=/usr/local/mysql/data
make && make install

1.6 添加開機啓動腳本

cp support-files/mysql.server /etc/rc.d/init.d/mysqld

1.7 添加masterA配置文件/etc/my.cnf

[client]
port = 3306
socket = /tmp/mysql.sock
[mysqld]
basedir = /usr/local/mysql
port = 3306
socket = /tmp/mysql.sock
datadir = /usr/local/mysql/data
pid-file = /usr/local/mysql/data/mysql.pid
log-error = /usr/local/mysql/data/mysql.err
server-id = 1
auto_increment_offset = 1
auto_increment_increment = 2 #奇數ID
log-bin = mysql-bin #打開二進制功能,MASTER主服務器必須打開此項
binlog-format=ROW
binlog-row-p_w_picpath=minimal
log-slave-updates=true
gtid-mode=on
enforce-gtid-consistency=true
master-info-repository=TABLE
relay-log-info-repository=TABLE
sync-master-info=1
slave-parallel-workers=0
sync_binlog=0
binlog-checksum=CRC32
master-verify-checksum=1
slave-sql-verify-checksum=1
binlog-rows-query-log_events=1
#expire_logs_days=5
max_binlog_size=1024M #binlog單文件最大值
replicate-ignore-db = mysql #忽略不一樣步主從的數據庫
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = test
replicate-ignore-db = zabbix
max_connections = 3000
max_connect_errors = 30
skip-character-set-client-handshake #忽略應用程序想要設置的其餘字符集
init-connect='SET NAMES utf8' #鏈接時執行的SQL
character-set-server=utf8 #服務端默認字符集
wait_timeout=1800 #請求的最大鏈接時間
interactive_timeout=1800 #和上一參數同時修改纔會生效
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES #sql模式
max_allowed_packet = 10M
bulk_insert_buffer_size = 8M
query_cache_type = 1
query_cache_size = 128M
query_cache_limit = 4M
key_buffer_size = 256M
read_buffer_size = 16K
skip-name-resolve
slow_query_log=1
long_query_time = 6
slow_query_log_file=slow-query.log
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 16M
[mysql]
no-auto-rehash
[myisamchk]
key_buffer_size = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
[mysqldump]
quick
max_allowed_packet = 16M
[mysqld_safe]

1.8 特別參數說明

log-slave-updates = true #將複製事件寫入binlog,一臺服務器既作主庫又作從庫此選項必需要開啓
#masterA自增加ID
auto_increment_offset = 1
auto_increment_increment = 2 #奇數ID
#masterB自增長ID
auto_increment_offset = 2
auto_increment_increment = 2 #偶數ID

1.9 添加masterB配置文件/etc/my.cnf

[client]
port = 3306
socket = /tmp/mysql.sock
[mysqld]
basedir = /usr/local/mysql
port = 3306
socket = /tmp/mysql.sock
datadir = /usr/local/mysql/data
pid-file = /usr/local/mysql/data/mysql.pid
log-error = /usr/local/mysql/data/mysql.err
server-id = 2
auto_increment_offset = 2
auto_increment_increment = 2 #偶數ID
log-bin = mysql-bin #打開二進制功能,MASTER主服務器必須打開此項
binlog-format=ROW
binlog-row-p_w_picpath=minimal
log-slave-updates=true
gtid-mode=on
enforce-gtid-consistency=true
master-info-repository=TABLE
relay-log-info-repository=TABLE
sync-master-info=1
slave-parallel-workers=0
sync_binlog=0
binlog-checksum=CRC32
master-verify-checksum=1
slave-sql-verify-checksum=1
binlog-rows-query-log_events=1
#expire_logs_days=5
max_binlog_size=1024M #binlog單文件最大值
replicate-ignore-db = mysql #忽略不一樣步主從的數據庫
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = test
replicate-ignore-db = zabbix
max_connections = 3000
max_connect_errors = 30
skip-character-set-client-handshake #忽略應用程序想要設置的其餘字符集
init-connect='SET NAMES utf8' #鏈接時執行的SQL
character-set-server=utf8 #服務端默認字符集
wait_timeout=1800 #請求的最大鏈接時間
interactive_timeout=1800 #和上一參數同時修改纔會生效
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES #sql模式
max_allowed_packet = 10M
bulk_insert_buffer_size = 8M
query_cache_type = 1
query_cache_size = 128M
query_cache_limit = 4M
key_buffer_size = 256M
read_buffer_size = 16K
skip-name-resolve
slow_query_log=1
long_query_time = 6
slow_query_log_file=slow-query.log
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 16M
[mysql]
no-auto-rehash
[myisamchk]
key_buffer_size = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
[mysqldump]
quick
max_allowed_packet = 16M
[mysqld_safe]

1.10 初始化MySQL

cd /usr/local/mysql
scripts/mysql_install_db --user=mysql

1.11 爲啓動腳本賦予可執行權限並啓動MySQL

chmod +x /etc/rc.d/init.d/mysqld
/etc/init.d/mysqld start

2. 配置主從同步

2.1 添加主從同步帳戶

masterA上:

mysql> grant replication slave on *.* to 'repl'@'192.168.10.12' identified by '123456';
mysql> flush privileges;

masterB上:

mysql> grant replication slave on *.* to 'repl'@'192.168.10.11' identified by '123456';
mysql> flush privileges;

2.2 查看主庫的狀態

masterA上:

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)

masterB上

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

2.3 配置同步信息:

masterA上:

mysql> change master to master_host='192.168.10.12',master_port=3306,master_user='repl',master_password='123456',master_log_file='mysql-bin.000003',master_log_pos=437;
mysql> start slave;
mysql> show slave statusG;

顯示有以下狀態則正常:

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

masterB上:

#本人是測試環境,能夠保證沒數據寫入,不然須要的步驟是:先masterA鎖表-->masterA備份數據-->masterA解鎖表 -->masterB導入數據-->masterB設置主從-->查看主從

mysql> change master to master_host='192.168.10.11',master_port=3306,master_user='repl',master_password='123456',master_log_file='mysql-bin.000003',master_log_pos=120;
start slave;
mysql> show slave statusG;

顯示有以下狀態則正常:

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

3.測試主從同步

3.1 在masterA上建立一個數據庫測試同步效果

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
+--------------------+
4 rows in set (0.00 sec)
mysql> create database test01;
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
| test01 |
+--------------------+
5 rows in set (0.00 sec)
mysql> quit
Bye
[root@masterA data]#

3.2 到masterB查看是否已經同步建立數據庫

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
| test01 |
+--------------------+
5 rows in set (0.00 sec)
mysql> quit
Bye
[root@masterB data]#

4. 開啓MySQL5.6的GTID功能

masterA和masterB分別執行以下命令:

mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
mysql> change master to MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

5. 遇到的問題

一種主從報錯折騰了我半天:

Last_IO_Errno: 1236

Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not open log file'

後面修改主從同步相關 參數,確認緣由是my.cnf增長了以下參數:

log-bin = mysql-bin

relay-log = mysql-bin

Java架構師筆記-MySQL雙主(主主)架構方案

 

從正常主主同步時的二進制日誌文件顯示,有2套二進制日誌。所以推斷上面2個參數致使不能產生2套二進制文件,故致使二進制文件錯亂和丟失。

總結

以上就是MySQL雙主(主主)架構方案,分享給你們,但願你們知道什麼是MySQL雙主架構。

多寫多敲代碼,好的代碼與紮實的基礎知識必定是實踐出來的

最後,每一位讀到這裏的網友,感謝大家能耐心地看完。但願在成爲一名更優秀的Java程序員的道路上,咱們能夠一塊兒學習、一塊兒進步!都能贏取白富美,走向架構師的人生巔峯!

相關文章
相關標籤/搜索