1. 程式人生 > >最全mysql的復制和讀寫分離

最全mysql的復制和讀寫分離

最全 產生 程序 數據不一致 技術 server1 per 保存 ignore

mysql的復制和mysql的讀寫分離從來就不是一個簡單的話題,今天筆者就詳細來記錄一下我學習的mysql。
mysql日至類型有:二進制日誌,事務日誌,錯誤日誌,一般查詢日誌,中繼日誌,慢查詢日誌。

二進制日誌一般放在數據目錄,一般文件名叫mysql-bin.xxxx,當數據大到我們設定的最大大小的時候就會滾動,還有類似flush ,logs,服務器重啟都會引起滾動,在mysql下刪除日誌一般我們不實用rm來刪除,而是在mysql命令下使用PURGE來清除
二進制記錄的格式有基於語句的,有基於行的,有混合的。除了mysql-bin-xxx外還有一些mysql-bin-index的文件,這是msyql二進制日誌文件的縮影
文件。想查看當前mysql使用的二進制文件我們在mysql>下使用SHOW MASTER STATUS;
SHOW查看mysql二進制日誌中的相關內容,mysql> SHOW BINLOG EVENTS IN "file";
查看當前mysql上存在二進制日誌文件的列表。mysql> SHOW BINARY LOGS;
一個日誌一般會記錄:產生時間(timestamp); 位置(position) 時間本身(offset),

二進制日誌記錄日誌並不完善,所以如果不備份數據庫,僅僅靠二進制文件恢復數據可能不完善。所以最好的辦法就是把數據庫備份一邊


由於主服務器允許並行執行,例如擁有多顆CPU就能同時執行多個寫操作,但是向二進制日誌中寫入的話只允許一個一個寫入,所以向從服務器傳輸的時候也只能一個一個傳輸,所以從服務器會比主管服務器慢,甚至有可能慢很多。


如果MYSQL的復制是同步的話,用戶就需要等待主服務器上的二進制文件完全傳輸到從服務器的時候才能執行下一個操作,而這時不科學的,所以MYSQL上的復制都是異步的,半同步就是只要數據發送到從服務器的tcp/ip的緩存中就OK了,但是對於MYSQL來說這個不實用,因為mysql還需要將他們保存到中繼日誌中去,一個一個去讀的。所以半同步和異步是差不多的,所以mysql一般使用異步。mysql和drbd最大的不同就是mysql支持一主多從。

看下圖一,就是mysql的基本原理圖

技術分享

在一主多從的模式下,只要有一個從服務器返回以及保存成功的信息,我們就不再去管其他的從服務器,這種方式我們叫做半同步。
mysql在5.5之前是不支持半同步的,

從服務器的所有數據都是從主服務器上復制過來的,因為從服務器是備份用的,所以我們需要保存和主服務器一模一樣的數據,如果從服務器的數據和主服務器的數據不一樣,我們就失去了從服務器的意義,所以我們不容許從服務器寫操作和向主服務器傳送東西。

熱備份很復雜,而且容易產生數據不一致的情況,有了從服務器我們可以在從服務器上停止Mysql的服務,然後進行冷備份,這樣安全多了。

從服務器不需要二進制日誌,沒什麽作用,還拖延從服務器的速度

mysql還有多級輔助


為了讓我們的讀寫速度加快,我們可以給他們分配任務,只在主服務器上寫,只在從服務器上讀。但是那麽多從服務器呢,我們在在那個上邊讀呢,簡單,負載均衡器。在前邊找一個MYsql路由,如果我們想發起Mysql讀寫的時候,我i們需要聯系這個Mysql代理,它可以判斷我們執行是什麽操作,讀的話就聯系從服務器,寫的話就聯系主服務器,這就叫做Mysql的讀寫分離。如果我們的讀操作非常多,那樣我們怎麽能盡可能的讓我們的讀速度變快呢,我們怎麽才能知道我的讀操作是那個從服務器響應我們呢?簡單,添加一個LVS就行了。在前端添加一個directory就行了

技術分享

技術分享



如果directory壞掉了怎麽辦?MYSQL代理壞掉怎麽辦?好辦,都做成高可用,如下圖三技術分享為了加快速度,我們可以加上個共享緩存,無論那個服務器的查詢都可以暫時緩存到memcnche,以後無論那個服務器查詢先到 memcnche查詢。

為了增加我們的讀寫速度我們添加了很多的從服務器,但是這麽多從服務器難道每次我們都要從主服務器啟動一個線程把日誌從二進制日誌發送到從服務器的中繼日誌麽?這就會產生大量的IO,那樣速度還會快麽?基於這樣的情況,就產生了多級復制的辦法

多級復制,就是從從服務器中選出一個專門負責中轉主服務器的日誌發總給別的從服務器。

PHP不需要和Mysql發生關系,發生關系的是PHP語言開發的程序。
我們可以讓開發語言,我們在配置時候自己來解決讀寫的程序,只不過開發程序比較麻煩。

如果既不想讓前端程序變得復雜,又不想提供讀寫分離,這就是主主模式,但是我們並不建議使用。
如圖四,黑線代表我們開始的時候的順序,產生的數據,我們保存在二進制日誌裏,二進制日誌通過傳送到另一個服務器中的中繼日誌中,中繼日誌在通過本地服務器讀出保存在數據庫,並儲存在二進制日誌中,然後開始紅線的部分,和這樣一樣的進程,復制到第一個進程中。但是這樣大家發現沒有,這樣會陷入一個循環中,尷尬,那我們需要做的就是給進程添加一個編號,這樣我們不再本地運行相同ID的server,這樣就不會再二進制日誌中發送了。技術分享


雙主模型,其實無法實現平均負載寫操作的,因為兩個節點上的數據必須一模一樣,不然會出錯的。雙主模型還容易產生爽膚數據不一致導致崩潰的情況。


對於MYSQL來說一個主服務器可以帶多個從服務器,但是一個從不能帶多個主,如果各個主服務器都寫入不同的數據,從服務器完全復制過來會到時數據不一致或者沖突之類的。



配置MySQL復制基本步驟:
簡單的下載解壓就不說了,我們直接從配置開始把。

一,先配置主服務器

復制配置文件到/etc/my.cof
復制腳本到/etc/rc.d/in.d/mysqld
chkconfig -add mysqld
vim /etc/my.cnf
我們所有的和復制有關的配置都在mysqld這裏邊
我們需要把log-bin=master-bin這一項啟動起來


2、選擇一個惟一server-id =1
server-id = {0-2^32}
innodb_file_per_table = 1
datedir = /mydata/data

然後service mysqld start


然後把該文件配置到從服務器上去

3、創建具有復制權限的用戶
REPLICATION SLAVE
REPLICATION CLIENT

二、配置從服務器

1、啟用中繼日誌
添加relay-log = relay-log
添加relay-log-index = relay-log.index

2、選擇一個惟一的server-id = (一定不能等於主服務器)
server-id = {0-2^32}

3、連接至主服務器,並開始復制數據;
mysql> CHANGER MASTER TO MASTER_HOST=‘‘,MASTER_PORT=‘‘,MASTER_LOG_FILE=‘‘,MASTER_LOG_FIEL_POS=‘‘,MASTER_USER=‘‘,MASTER_PASSWORD=‘‘;
mysql>SHOW SLAVE STATUS\G(查看當前狀態
)
mysql> START SLAVE;(啟動服務)

mysql> START SLAVE IO_Thread; (YES為正常)
mysql> START SLAVE SQL_Thread; (YES為正常)

復制線程:
master: dump
slave: IO_Thread, SQL_Thread

怎麽把從服務器設置成只讀
在配置文件中添加
read-only = YES 重啟服務有效
但是對於擁有管理員身份的人無效

sync-binlog = ON
在主服務器上設定,用於事務安全;

所有的從服務器上的信息都會被保存在/mydata/daya/node2.magedu.com.err下邊


如何讓mysql實現半同步呢,這需要一個插件
這個插件在 /usr/local/mysql/lib/plugin裏邊有兩個文件 semisync_slave.so 和semisync_maste.so。一主一從

設置半同步步驟:

在Master和Slave的mysql命令行運行如下代碼:

# On Master
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME ‘semisync_master.so‘;
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
mysql> SET GLOBAL rpl_semi_sync_master_timeout = 1000;
設置是否啟用和超時時間
# On Slave
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME ‘semisync_slave.so‘;
mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;
mysql> STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;

在Master和Slave的my.cnf中編輯:

# On Master
[mysqld]
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000 # 1 second

# On Slave
[mysqld]
rpl_semi_sync_slave_enabled=1


# 也可通過設置全局變量的方式來設置,如下:
set global rpl_semi_sync_master_enabled=1
# 取消加載插件
mysql> UNINSTALL PLUGIN rpl_semi_sync_master;




設置主-主復制:
1、在兩臺服務器上各自建立一個具有復制權限的用戶;
2、修改配置文件:
# 主服務器上
[mysqld]
server-id = 10
log-bin = mysql-bin
relay-log = relay-mysql
relay-log-index = relay-mysql.index
auto-increment-increment = 2
auto-increment-offset = 1

# 從服務器上
[mysqld]
server-id = 20
log-bin = mysql-bin
relay-log = relay-mysql
relay-log-index = relay-mysql.index
auto-increment-increment = 2
auto-increment-offset = 2

3、如果此時兩臺服務器均為新建立,且無其它寫入操作,各服務器只需記錄當前自己二進制日誌文件及事件位置,以之作為另外的服務器復制起始位置即可

server1|mysql> SHOW MASTER STATUS\G
************************** 1. row ***************************
File: mysql-bin.000001
Position: 710
Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)

server2|mysql> SHOW MASTER STATUS\G
mysql> SHOW MASTER STATUS\G
*************************** 1. row ***************************
File: mysql-bin.000003
Position: 811
Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)

4、各服務器接下來指定對另一臺服務器為自己的主服務器即可:
server1|mysql> CHANGE MASTER TO ...,MASTER_LOG_FILE=‘mysql-bin.000003‘, MASTER_LOG_POS=811

server2|mysql> CHANGE MASTER TO ...,MASTER_LOG_FILE=‘mysql-bin.000001‘, MASTER_LOG_POS=710

最全mysql的復制和讀寫分離