1、MySQL複製的三種模式html
MySQL當前存在的三種複製模式有:異步模式、半同步模式和組複製模式,先了解一下三種模式的工做方式。mysql
異步複製是MySQL最先的也是當前使用最多的複製模式,異步複製提供了一種簡單的主-從複製方法,包含一個主庫(master)和備庫(一個,或者多個)之間,主庫執行並提交了事務,在這以後(所以才稱之爲異步),這些事務纔在從庫上從新執行一遍(基於statement)或者變動數據內容(基於row),主庫不檢測其從庫上的同步狀況。在服務器負載高、服務壓力大的狀況下主從產生延遲一直是其詬病。工做流程簡圖以下:算法
MySQL5.5的版本在一步同步的基礎之上,以插件的形式實現了一個變種的同步方案,稱之爲半同步(semi-sync replication)。這個插件在源生的異步複製上,添加了一個同步的過程:當從庫接收到了主庫的變動(即事務)時,會通知主庫。主庫上的操做有兩種:接收到這個通知之後纔去commit事務;接受到以後釋放session。這兩種方式是由主庫上的具體配置決定的。當主庫收不到從庫的變動通知超時時,由半同步複製自動切換到異步同步,這樣就極大了保證了數據的一致性(至少一個從庫),可是在性能上有所降低,特別是在網絡不穩定的狀況下,半同步和同步之間來回切換,對正常的業務是有影響的。其工做流程簡圖以下:sql
不管是異步複製仍是半同步複製,都是一個主下面一個從或是多個從的模式,在高併發下高負載下,都存在延遲狀況,此時若是主節點出現異常,那麼就會出現數據不一致的狀況,數據可能會丟,在金融級數據庫中是不能容忍的。在這種狀況下,急需出現一種模式來解決這些問題。在MySQL5.7.17的版本中,帶着這些期待,新的複製模式組複製產生並GA了(本文的測試等數據均基於MySQL5.7.17)。數據庫
組複製的工做流程圖以下:bootstrap
MySQL組複製是一個MySQL插件,它創建在現有的MySQL複製基礎結構上,利用了二進制日誌,基於行的日誌記錄和全局事務標識符等功能。它集成了當前的MySQL框架,如性能模式、插件和服務基礎設施等。服務器
組複製(Group Replication)基於分佈式一致性算法(Paxos協議的變體)實現,一個組容許部分節點掛掉,只要保證絕大多數節點仍然存活而且之間的通信是沒有問題的,那麼這個組對外仍然可以提供服務,它是一種被使用在容錯系統中的技術。Group Replication(複製組)是由可以相互通訊的多個服務器(節點)組成的。在通訊層,Group replication實現了一系列的機制:好比原子消息(atomic message delivery)和全序化消息(total ordering of messages)。這些原子化,抽象化的機制,爲實現更先進的數據庫複製方案提供了強有力的支持。MySQL Group Replication正是基於這些技術和概念,實現了一種多主全更新的複製協議。簡而言之,一個Group Replication就是一組節點,每一個節點均可以獨立執行事務,而讀寫事務則會在於group內的其餘節點進行協調以後再commit。所以,當一個事務準備提交時,會自動在group內進行原子性的廣播,告知其餘節點變動了什麼內容/執行了什麼事務。這種原子廣播的方式,使得這個事務在每個節點上都保持着一樣順序。這意味着每個節點都以一樣的順序,接收到了一樣的事務日誌,因此每個節點以一樣的順序重演了這些事務日誌,最終整個group保持了徹底一致的狀態。然而,不一樣的節點上執行的事務之間有可能存在資源爭用。這種現象容易出如今兩個不一樣的併發事務上。假設在不一樣的節點上有兩個併發事務,更新了同一行數據,那麼就會發生資源爭用。面對這種狀況,Group Replication斷定先提交的事務爲有效事務,會在整個group裏面重放,後提交的事務會直接中斷,或者回滾,最後丟棄掉。所以,這也是一個無共享的複製方案,每個節點都保存了完整的數據副本。網絡
從其工做的原理能夠看出,Group Replication基於Paxos協議的一致性算法校驗事務執行是否有衝突,而後順序執行事務,達到最終的數據一致性,也就意味着部分節點能夠存在延遲。能夠設置多主同時寫入和單主寫入,經過設置group_replication_single_primary_mode來進行控制是多主仍是單主,官方推薦單主寫入,容許延遲,但延遲過大,則會觸發限流規則(可配置的),整個集羣會變的很慢,性能大打折扣。session
在MySQL的底層,GR增長了另外的API層來實現所須要的功能。程序結構上,GRAPI主要分爲三部分:多線程
1:capture 追蹤當前正在執行的事務的上下文。
2:applier 執行遠程事務傳輸到本地的日誌到本地數據庫。
3:recovery 負責分佈式環境下的節點恢復,以及相關的數據回追,失敗處理等。
在這幾個主要API層的下面,是統一的複製協議邏輯處理層,這一層主要是統一應用層的各類調用。在更下層,則是通用程度更高的分佈式通信層,處於調用便利,分佈式通信曾對上提供使用的API,API的下面,是Paxos實現的分佈式通信協議組件,這個組件與集羣中其餘節點一塊兒,造成一個虛擬概念化的分佈式集羣。
這個壓縮主要是指MySQL的bin-log壓縮,所使用的壓縮算法是LZ4。當網絡帶寬是瓶頸時,消息壓縮能夠在組通訊級別提供高達30-40%的吞吐量改進,這在網絡傳輸壓力比較大的組中是尤其重要的。LZ4能很好的支持多線程環境,得到更高的壓縮和解壓速度。如下是壓縮算法LZ4的壓縮和解壓狀況:
壓縮發生在組通訊引擎級別,以前數據被交給組通訊線程,因此它發生在mysql用戶會話線程的上下文中。事務有效網絡負載能夠在被髮送到組以前被壓縮,而且在被接收時被解壓縮。壓縮是有條件的,而且取決於配置的閾值。默認狀況下啓用壓縮,此外,它並不要求組中的全部服務器節點都啓用壓縮機制,在接收到消息時,成員檢查消息信封以驗證它是否被壓縮,若是須要,則成員解壓縮該事務,而後將其傳遞到上層。
默認狀況下啓用壓縮,閾值爲1000000字節(1MB)。壓縮閾值(以字節爲單位)能夠設置爲大於默認值。在這種狀況下,只有具備大於閾值的有效負載的事務被壓縮。下面是如何設置壓縮閾值的示例。
STOP GROUP_REPLICATION; SET GLOBAL group_replication_compression_threshold= 2097152; START GROUP_REPLICATION;
這將壓縮閾值設置爲2MB。若是事務生成的有效內容大於2MB的複製消息,例如大於2MB的二進制日誌事務條目,則會對其進行壓縮。禁用壓縮設置閾值爲0。注意:修改這個閾值是須要重啓組複製的。
消息壓縮流程圖以下:
1. 全部涉及的數據都必須發生在InnoDB存儲引擎的表內。
2. 全部的表必須有明確的主鍵定義。
3. 網絡地址只支持IPv4。
4. 須要低延遲,高帶寬的網絡。
5. 目前集羣限制最多容許9個節點。
6. 必須啓用binlog。
7. binlog 格式必須是row格式。
8. 必須打開gtid模式。
9. 複製相關信息必須使用表存儲。
10.事務寫集合(Transaction write set extraction)必須打開。(這個目前與savepoint衝突,這也是致使mysqldump沒法備份GR實例的緣由)
11. log slave updates必須打開。
12. binlog的checksum目前不支持。
13. 因爲事務寫集合的干擾,沒法使用savepoint。
14. SERIALIZABLE 隔離級別目前不支持。
15. 對同一個對象,在集羣中不一樣的實例上,並行地執行DDL(哪怕是相互衝突的DDL)是可行的,但會致使數據一致性等方面的錯誤,目前階段不支持在多節點同時執行同一對象的DDL。
16. 外鍵的級聯約束操做目前的實現並不徹底支持,不推薦使用。
依據組複製的要求和限制,如下設置根據MySQL組複製要求配置複製:
server_id = 1
gtid_mode = ON
enforce_gtid_consistency = ON
master_info_repository = TABLE
relay_log_info_repository = TABLE
binlog_checksum = NONE
log_slave_updates = ON
log_bin = binlog
binlog_format = ROW
此時my.cnf文件可確保服務器配置,並指示實例化一個給定的配置下的複製基礎設施。如下部分配置服務器的組複製設置。具體參數比較簡單,不在這裏贅述,可參見官方說明:
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name =「aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa」
loose-group_replication_start_on_boot = off
loose-group_replication_local_address ="127.0.0.1:24901」
loose-group_replication_group_seeds =「127.0.0.1:24901,127.0.0.1:24902,127.0.0.1:24903」
loose-group_replication_bootstrap_group = off
具體的組複製安裝部署比較簡單,網上和官方說明都有說明,在這裏就不闡述安裝部署這塊了。
組複製分爲多主和單主兩種模式,默認是單主模式,也是官方推薦的組複製模式。單個集羣中不能同時使用兩種模式,例如一個配置在多主模式,而另外一個在單主模式。要在模式之間切換,須要使用不一樣的操做配置從新啓動集羣。不管部署模式如何,組複製不處理客戶端故障切換,它必須由應用程序自己、鏈接器或中間件框架(如代理或路由器)等處理。
在此模式下,組具備設置爲讀寫模式的單主實例,主節點一般是用於解析組的第一個服務器,組中的其餘其餘節點都自動設置爲只讀模式(即,超級只讀),全部其餘加入的節點自動識別主節點並設置爲本身爲只讀。
在單主機模式下,將禁用在多主機模式下部署的某些檢查,由於系統會強制每次只有一個寫入節點。例如,容許對具備級聯外鍵的表進行更改,而在多主模式下不容許。在主節點故障時,自動選舉機制選擇下一個主節點。經過按字典順序(使用其UUID)並選擇列表中的第一個節點來排序剩餘的節點來選擇下一個主節點。若是主節點從組中刪除,則執行選擇,並從組中的其他節點中選擇新的主節點,這個選擇按照詞典順序排序節點UUID並選擇第一個來執行。一旦選擇了新的主節點,其餘節點將設置爲從節點,從節點爲只讀。以下圖:
在多主模式下,沒有單個主模式的概念,也沒有選舉程序,由於沒有節點發揮任何特殊的做用。加入組時,全部服務器都設置爲讀寫模式。
在多主要模式下部署時,將檢查語句以確保它們與模式兼容。在以多主模式部署組複製時進行如下檢查:
1:若是事務在SERIALIZABLE隔離級別下執行,則在將其與組同步時,它的提交將失敗。
2:若是事務對具備級聯約束的外鍵執行,則事務在與組同步時沒法提交。
這些檢查可經過設置選項停用 group_replication_enforce_update_everywhere_checks 到FALSE。當在單主要方式部署,該選項必須設置爲 FALSE。以下圖:
目前MySQL官方沒有發佈鏈接組複製專用的客戶端(如MongoDB鏈接複製集的客戶端),在實際的應用中若是發生故障,須要客戶端本身來處理。對於單主模式的話,若是主節點發生故障,客戶端須要判斷新的主節點是誰,而後把寫切換到新的主節點,基本上和當前的異步同步的主從切換同樣,而且新的主節點是集羣自動產生,不可控;多主模式須要在客戶端進行節點可用性檢查,當其中的一個寫節點不可用時自動使用其餘可用節點。
在實際生產中,綜合兩種組複製模式的故障切換,可使用多主模式,指定其中一個節點爲主節點,其餘節點置爲只讀節點,這樣主節點故障時,新的主節點可控。
目前版本測試併發進行大數據操做和DDL操做時,kill掉大事務,有概率形成集羣不可用;在insert into …….select……limit……這種大事務支持很差,可能形成集羣不用;多主模式進行DDL操做須要集羣內全部節點都爲ONLINE狀態纔可執行,處於ERROR和RECOVERING狀態時有概率致使集羣堵塞,嚴重時集羣不可用。
在組複製集羣其中的一個節點上執行數據庫備份時,無論使用mysqldump(這個不能使用--single-transaction參數,生產中不建議使用mysqldump備份集羣數據)或是使用xtrabackup的QPS降低40%,而且備份節點基本中止讀寫。在測試備份文件導入數據時,多主模式要比單主模式慢。推薦使用組複製+異步複製方式,在異步複製的從節點上進行數據庫備份。
由於組複製同步仍是基於二進制日誌來進行同步的,清理某個節點bin-log時,必須斷定這個日誌文件是否還在使用,若是在使用,則絕對不能刪除,若是刪除,則整個集羣直接ERROR。
目前MySQL5.7.17的版本中沒法直觀查看節點同步延遲,也沒法獲取延遲多少,無論是時間或事物數,這個打開MySQL的Debug模式,能夠獲取到節點的延遲事務狀況。
組複製的延遲對集羣是有影響的,一旦出現延遲(默認延遲25000個事務),則啓動流量控制(Flow Control),每一個週期性能衰減當前的10%,直到集羣不可用(但集羣節點狀態爲online),單個節點慢整個集羣全慢。
集羣中的每一個節點都會驗證並應用該組提交的事務,有關校驗和應用程序過程的統計信息對於瞭解應用程序隊列如何增加,已找到多少衝突,檢查了多少事務,在哪裏提交了哪些事務等等很是有用。表 performance_schema.replication_group_member_stats 提供與事務認證過程的相關信息,但沒有延遲信息。相關字段解釋以下:
字段 |
描述 |
Channel_name |
組複製通道的名稱。 |
Member_ID |
表明當前鏈接到的成員服務器UUID。組中的每一個節點具備不一樣的值,是一個惟一鍵,由於它對每一個成員是惟一的。 |
Count_Transactions_in_queue |
隊列中等待衝突檢測檢查的事務數。一旦檢查到衝突,而且他們經過檢查,他們將排隊等待應用。 |
Count_transactions_checked |
表示已檢查衝突的事務數。 |
Count_conflicts_detected |
表示未經過沖突檢測檢查的事務數。 |
Count_transactions_validating |
表示衝突檢測數據庫的當前大小(每一個事務通過驗證的數據庫)。 |
Transactions_committed_all_members |
表示已在當前視圖的全部成員上成功提交的事務。這以固定的時間間隔更新。 |
Last_conflict_free_transaction |
顯示最後一次無衝突校驗檢查的事務標識符。 |
無論是多寫仍是單寫,都並不是是強一致性,均容許有延遲,他在校驗完事務是否衝突後把當前廣播到各個節點並肯定各個節點收到事務後即進入下一個事物的衝突檢測,此時每一個節點只是拿到了全部事務的執行序列,保證了事務最終順序執行,從而保證數據的最終一致性,但同一時刻並不是強一致性的。
節點越多性能損耗越大,三個節點比較合適。節點故障可能有腦裂等問題:如5個節點分佈在兩個機房,機房間網絡斷掉分爲兩個部分,2個集羣的機房不可用,3個節點的可用,而三個節點的機房網絡有問題,此時若是想使兩個節點的機房可用,須要從新對兩個節點作集羣重組,三個節點的就沒法恢復到兩個節點中去;三節點中其中一個節點宕機,其餘兩個正常節點可用,故障節點重啓沒有加入到集羣時,此時這個節點以單實例存在可讀寫,此時會發生腦裂。
測試過程當中使用TC命令來模擬網絡延遲:
tc qdisc add dev eth0 root netem delay 50ms 10ms 增長網絡延遲50ms,10ms左右的浮動
tc qdisc del dev eth0 root netem delay 50ms 10ms 刪除網絡延遲
通過測試網絡延遲對比組複製MySQL的QPS:網絡延遲設置50ms和正常的對比,QPS下降至少1/3,甚至1/2,網絡延遲對性能影響挺大。如下是測試狀況:
MySQL官方網站提到了組複製的彈性自動擴展,通過實際測試,這種擴展在生產中是不現實的。可用於生產的彈性擴展要求新加入一個集羣,集羣中的數據徹底由集羣來完成自動同步,但因爲組複製是基於二進制日誌來進行同步的,生產中是不可能完整保留所有的二進制日誌,在新加入的節點須要先備份出集羣的全量數據,而後根據同步位置去追事務達到數據的一致後節點狀態online狀態,其實和以前異步同步搭建主從同樣。而且官方提示若是恢復時的延遲過大,可能也沒法正常達到追到最新數據的位置。
官方說明中關於故障處理的時候有一句話:組複製不處理客戶端故障切換,它必須由應用程序自己,鏈接器或中間件框架(如代理或路由器)處理。官方一再強調MySQL組複製提供了高可用、高彈性、可靠的MySQL服務,那麼官方是否提供一套相似MongoDB複製集的客戶端組件來支持那?
目前的解決方法就是和異步複製的切換差很少,使用域名切換或是本身實現一套高可用的客戶端鏈接方式。但就目前來講效率最高的是結合本身的業務,修改組複製故障處理的源碼,當檢測到寫節點故障時結合本身的域名切換來處理。但這樣對DBA來講須要源碼開發能力,相對要求比較高。
在單主模式下,不能直觀的獲取主庫的IP地址,使用如下命令能夠獲取到主節點的UUID:
mysql> SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME ='group_replication_primary_member';
+ -------------------------------------- +
| VARIABLE_VALUE |
+ -------------------------------------- +
| 69e1a3b8-8397-11e6-8e67-bf68cbc061a4 |
+ -------------------------------------- +
1行(0,00秒)
使用SELECT * FROM performance_schema.replication_group_members能夠查看到UUID對應到的MEMBER_HOST,而MEMBER_HOST指的是主機名,須要在MySQL的配置文件中指定report-host爲IP地址,這樣就能夠兩個表關聯查詢到主庫的IP地址。
從測試的狀況來看,對大事務等的支持不夠,運維管理方面作的不友好,相關組複製的配套監控、客戶端等不完善,有一部分問題是能夠規避和曲線解決的,有一部分須要源碼層面的支持;在性能上和PXC對比,要優於PXC,這個和各自的複製協議不一樣分不開的。
MySQL組複製提供了高可用、高彈性、可靠的MySQL服務,旨在打造金融級MySQL集羣。在忽略網絡延遲的狀況,能夠輕鬆的實現多活和異地調用就近寫庫,這一點是業務上比較期待的。組複製是MySQL將來的一個發展趨勢,相信在將來的版本中會更加的完善,期待成熟版本。
參考文檔:http://dev.mysql.com/doc/refman/5.7/en/group-replication.html