MySQL雙主(主主)架構方案與配置Mysql-proxy,實現讀寫分離

MySQL雙主(主主)架構方案

企業中數據庫的高可用是必不可缺的。中小企業使用mysql主從方案,一主多從,讀寫分離等,但單主出現故障時,從庫須要切換主庫做改動。而若是是雙主或多主,就會增長mysql入口,增長高可用。多主須要考慮到自增加id問題。須要特別設置配置文件。總之,主之間設置自增加ID相互不衝突就能完美解決自增加ID衝突問題。javascript

主從同步複製原理

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

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

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

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

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

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

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

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

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

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

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

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

架構簡易圖:java

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

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

2.官方Mysql5.6版本linux

搭建過程:

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

1.1 yum安裝依賴包

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

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

groupadd -g 27 mysqlsql

adduser -u 27 -g mysql -s /sbin/nologin mysql數據庫

1.3 下載MySQL源碼包

mkdir -p /data/packages/srcbootstrap

cd /data/packages/wget http://distfiles.macports.org/cmake/cmake-3.2.3.tar.gzwget http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.34.tar.gzvim

1.4 建立mysql數據目錄

mkdir -p /usr/local/mysql/data

1.5 解壓編譯安裝cmake、MySQL

cd /data/packages/srctar -zxvf ../cmake-3.2.3.tar.gz

cd cmake-3.2.3/

./bootstrap

gmakemake 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/datamake && 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=TABLEsync-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=TABLEsync-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 status\G;

 

顯示有以下狀態則正常:

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 status\G;

顯示有以下狀態則正常:

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

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

配置Mysql-proxy,實現讀寫分離

環境描述:
操做系統:CentOS6.5 64 位
mysql主服務器 Master:172.25.17.19

mysql從服務器 Slave1:172.25.17.20

mysql從服務器 Slave2:172.25.17.21

調度服務器 MySQL-Proxy:172.25.17.7 

一、安裝 mysql-proxy
實現讀寫分離是有 lua 腳本實現的,如今 mysql-proxy 裏面已經集成,無需再安裝
下載:http://dev.mysql.com/downloads/mysql-proxy/ 必定要下載對應的版本 
[root@proxy ~]# rpm -ivh mysql-proxy-0.8.1-1.el6.x86_64.rpm

二、將rw-splitting.lua 腳本複製到/lib 下
[root@proxy ~]# cp rw-splitting.lua /lib

三、修改mysql-proxy主配置文件/etc/sysconfig/mysql-proxy

[root@proxy ~]# vim /etc/sysconfig/mysql-proxy

ADMIN_USER="proxy"                                            #主從 mysql 共有的用戶

ADMIN_PASSWORD="123456"                              #用戶的密碼

ADMIN_LUA_SCRIPT="/lib/rw-splitting.lua"        #指定管理腳本

PROXY_USER="root"                                              #運行 mysql-proxy用戶

                                             #添加以下代碼:[如下代碼需寫在一行內]

PROXY_OPTIONS="--proxy-address=172.25.17.7:4040

 

--proxy-read-only-backend-addresses=172.25.17.20:3306--proxy-read-only-backend-addresses=172.25.17.21:3306--proxy-backend-addresses=172.25.17.19:3306--proxy-lua-script=/lib/rw-splitting.lua

 --daemon"

                                             #mysql-proxy 運行 ip 和端口,不加端口,默認 4040

四、修改讀寫分離配置文件

[root@proxy ~]vim /lib/rw-splitting.luaif not proxy.global.config.rwsplit then

proxy.global.config.rwsplit = {

min_idle_connections = 1,                    #默認超過 4個鏈接數時,纔開始讀寫分離,改成 1

max_idle_connections = 1,                   #默認 8,改成1

is_debug = false}

end

                                           #這裏的 4 、8 是指定連接數,作測試時調整爲 1

五、設置mysql-proxy 開機啓動,並啓動mysql-proxy

[root@proxy ~]# chkconfig mysql-proxy on[root@proxy ~]# service mysql-proxy start[root@proxy ~]# netstat -tnlp | grep mysql-proxy

六、在master數據庫受權mysql-proxy訪問
[root@master ~]#  mysql -puplooking
grant all on *.* to 'proxy'@'172.25.17.7' identified by '123456';
grant all on *.* to 'proxy'@'rhel6' identified by '123456';
flush privileges;

 

7 、測試讀寫分離

測試讀寫分離,要讓兩臺服務器數據有偏差才行,因此暫停slave1(172.25.17.20)上的從服務:

mysql -puplooking stop slave;

在 master(172.25.17.19) 服務器上修改數據:

 mysql> create tabletest.t1(id int);

 mysql> insert intotest.t1 values (1);mysql> insert into test.t1 values (3);

 mysql> insert intotest.t1 values (2);mysql> insert into test.t1 values (4);

在 slave1(172.25.17.20) 服務器上修改數據:

 mysql> create tabletest.t1(id int);

 mysql> insert into test.t1values (5);

 mysql> insert intotest.t1 values (6);

 

在 調度服務器mysql-proxy 上打開若干個終端遠程訪問數據庫,讀取數據:

[root@proxy ~]yum -y install mysql        #安裝數據庫添加mysql啓動命令

[root@proxy ~]mysql -uproxy -p123456 -h172.25.17.7 -P4040

                                                                    #遠程訪問數據庫

mysql> select * from test1.t1;

+------+| id   |

+------+|    1 ||    2 ||    3 ||    4 |

+------+

4 rows in set (0.00 sec)

 

mysql> select * from test01.t1;

+------+| id   |

+------+|    5 ||    6 |

+------+

2 rows in set (0.00 sec)

顯示結果不同,證實配置成功。屢次嘗試以上兩行代碼直到顯示不一樣結果。

試驗結束在slave1服務器上slave start恢復主從同步。

讀寫分離,延遲是個大問題
  在 slave 服務器上執行 show slave status,
能夠看到不少同步的參數,要注意的參數有:
  Master_Log_File:slave 中的 I/O 線程當前正在讀取的 master 服務器二進制式日誌文件名.
  Read_Master_Log_Pos:在當前的 master 服務器二進制日誌中,slave 中的 I/O 線程已經讀取的位置
  Relay_Log_File:SQL 線程當前正在讀取與執行中繼日誌文件的名稱
  Relay_Log_Pos:在當前的中繼日誌中,SQL 線程已讀取和執行的位置
  Relay_Master_Log_File:由 SQL 線程執行的包含多數近期事件的 master 二進制日誌文件的名稱
  Slave_IO_Running:I/O 線程是否被啓動併成功鏈接到 master
  Slave_SQL_Running:SQL 線程是否被啓動
  Seconds_Behind_Master:slave 服務器 SQL 線程和從服務器 I/O 線程之間的差距,單位爲秒計

slave 同步延遲狀況出現:
1.Seconds_Behind_Master 不爲了,這個值可能會很大
2.Relay_Master_Log_File 和 Master_Log_File 顯示 bin-log 的編號相差很大,說明 bin-log 在 slave 上
沒有及時同步,因此近期執行的 bin-log 和當前 I/O 線程所讀的 bin-log 相差很大
3.mysql 的 slave 數據庫目錄下存在大量的 mysql-relay-log 日誌,該日誌同步完成以後就會被系統自動
刪除,存在大量日誌,說明主從同步延遲很厲害

mysql 主從同步原理
主庫針對讀寫操做,順序寫 binlog,從庫單線程去主庫讀"寫操做的 binlog",從庫取到 binlog 在本地原
樣執行(隨機寫),來保證主從數據邏輯上一致.
mysql 的主從複製都是單線程的操做,主庫對全部 DDL 和 DML 產生 binlog,binlog 是順序寫,因此
效率很高,slave 的 Slave_IO_Running 線程到主庫取日誌,效率比較高,下一步問題來 了,slave 的
slave_sql_running 線程將主庫的 DDL 和 DML 操做在 slave 實施。DML,DDL 的 IO 操做是隨即的,
不能順序的,成本高不少,還有可能 slave 上的其餘查詢產生 lock,因爲 slave_sql_running 也是單線
程的,因此 一個 DDL 卡住了,需求需求執行一段時間,那麼全部以後的 DDL 會等待這個 DDL 執行完
纔會繼續執行,這就致使了延遲.因爲 master 能夠併發,Slave_sql_running 線程卻不能夠,因此主庫執
行 DDL 需求一段時間,在 slave 執行相同的 DDL 時,就產生了延遲.

主從同步延遲產生緣由
當主庫的 TPS 併發較高時,產生的 DDL 數量超過 Slave 一個 sql 線程所能承受的範圍,那麼延遲就產
生了,固然還有就是可能與 slave 的大型 query 語句產生了鎖等待
首要緣由:數據庫在業務上讀寫壓力太大,CPU 計算負荷大,網卡負荷大,硬盤隨機 IO 過高
次要緣由:讀寫 binlog 帶來的性能影響,網絡傳輸延遲

主從同步延遲解決方案
架構方面
1.業務的持久化層的實現採用分庫架構,mysql 服務可平行擴展分散壓力
2.單個庫讀寫分離,一主多從,主寫從讀,分散壓力。
3.服務的基礎架構在業務和 mysql 之間加放 cache 層
4.不一樣業務的 mysql 放在不一樣的機器
5.使用比主加更了的硬件設備做 slave

主要是讓mysql壓力變小,延遲天然就會變小。

硬件方面:
採用好的服務器
mysql 主從同步加速
一、sync_binlog 在 slave 端設置爲 0
二、–logs-slave-updates 從服務器從主服務器接收到的更新不記入它的二進制日誌。
三、直接禁用 slave 端的 binlog
四、slave 端,若是使用的存儲引擎是 innodb,innodb_flush_log_at_trx_commit =2
從文件系統自己屬性角度優化

master 端
修改 linux、Unix 文件系統中文件的 etime 屬性,能夠 經過設置文件系統的 mount 屬性,組織操做系統寫 atime 信息

打開/etc/fstab,加上 noatime 參數
/dev/sdb1 /data reiserfs noatime 1 2
而後從新 mount 文件系統
#mount -oremount /data
主庫是寫,對數據安全性較高,好比 sync_binlog=1,innodb_flush_log_at_trx_commit = 1 之類的設置是須要的
而 slave 則不須要這麼高的數據安全,徹底能夠講 sync_binlog 設置爲 0 或者關閉
binlog,innodb_flushlog 也能夠設置爲 0 來提升 sql 的執行效率

一、sync_binlog=1 o
MySQL 提供一個 sync_binlog 參數來控制數據庫的 binlog 刷到磁盤上去。
默認,sync_binlog=0,表示 MySQL 不控制 binlog 的刷新,

二、innodb_flush_log_at_trx_commit (這個很管用)

默認值 1 的意思是每一次事務提交或事務外的指令都須要把日誌寫入(flush)硬盤,這是很費時的,設成 2 對於不少運用,特別是從 MyISAM 錶轉過來的是能夠的,它的意思是不 寫入硬盤而是寫入系統緩存。值 2 只會在整個操做系統 掛了時纔可能丟數據。 

3.進行分庫分表處理,這樣減小數據量的複製同步操做 

相關文章
相關標籤/搜索