上篇文章《分布式數據存儲 - MySQL主從復制》,我們說到MySQL主從復制很好的保障了從庫,讀的高可用性。so,問題來了:
1、針對主庫,寫的高可用性又是如何做到高可用性?
2、如果需要對Master進行維護或宕機,為了不影響寫服務,我們可能會將Slave節點提升為Master來提供寫服務。當Master節點可以正常提供服務時,可能會發現Master中數據和實際數據不一致的情況,就不得不 反轉原來的Master-Slave關系重新搭建Replication環境,進行新的主從節點數據同步,新的Slaver節點提供讀服務。這種方式我們不僅要重新搭建Replication環境,還要處理數據同步postion位置,甚至數據沖突。那么有沒有更好的處理方法?
一般的解決方法采用雙主模式。
一、MySQL雙主復制(Dual Master)

Dual Master,既是master,又是另一台服務器的slave。這樣,任何一方所做的變更,都會通過復制應用到另外一方的數據庫中。
雙主復制的復制過程和主從復制類似的,這里就不再贅述。
雙主復制需要注意哪些問題?數據完整性、數據一致性和主鍵沖突
1、盡可能通過業務場景設計來規避,對於同一個庫,同一張表,同一個記錄中的同一字段的兩地變更,引發的數據一致性判斷沖突。
2、避免使用數據庫自增類主鍵方案,而使用分布式全局ID,避免雙主雙寫並同步復制可能引發主鍵沖突。
3、雙向同步復制Dual Master潛在可能引發循環同步的問題。
- 在MySQL的Binary Log中記錄了當前MySQL的server-id,而且這個參數也是我們搭建MySQLReplication的時候必須明確指定,並且參數值不一致。一旦有了server-id的值之后,MySQL就很容易判斷某個變更是從哪一個MySQL Server最初產生的,所以就很容易避免出現循環復制的情況。
- 如果我們不打開記錄Slave的Binary Log的選項(--log-slave-update)的時候,MySQL根本就不會記錄復制過程中的變更到BinaryLog中,就更不用擔心可能會出現循環復制的情形了。
我們從MySQL的Dual Master的循環復制方案中看出,就是在Binary Log中打上標記,就有辦法判斷哪些Binary Log是復制產生的,並將其過濾。
復制過濾可以讓你只復制服務器中的一部分數據,有兩種復制過濾:在master上過濾二進制日志中的事件;在slave上過濾中繼日志中的事件。

二、自定義標記SQL方案
Dual Master的循環復制方案過於依賴配置,可以考慮一種通用的標記 SQL 方案。簡單來說,就是在同步復制入庫時插入特殊的標記 SQL 語句來標記這是來自復制程序的變更,這個標記 SQL 會進入 binlog 中。而在復制程序讀取時,通過識別這個標記 SQL 來過濾判斷。
binlog 中存儲了對數據產生變更影響的的 SQL 語句,這些 SQL 語句組成了一段一段的事務,如下圖所示:

(http://www.cnblogs.com/mindwind/p/4993708.html)
綠色區是業務運行產生的正常事務,紅色區是復制程序寫入產生的事務,其中藍色塊是標記 SQL。標記 SQL 分別在事務開始后與事務結束前,標記 SQL 更新一張預定義的區別於業務表的標記表。那么每次復制程序去批量讀取 binlog 內容時,可能存在下面 5 種情況,如下圖所示:

(http://www.cnblogs.com/mindwind/p/4993708.html)
- 批量讀取范圍全落在綠色區內。
- 批量讀取范圍起點落在綠色區,終點落在紅色區。
- 批量讀取范圍起點落在紅色區,終點落在綠色區。
- 批量讀取范圍起點和終點都在綠色區,但中間涵蓋了一段紅色區。
- 批量讀取范圍全落在紅色區。
如上只有第 5 種情況,一個事務被拆成 3 段來同步。中間一段因為沒有事務頭和尾的標記,復制程序讀取時將無法判斷,導致循環同步,需要避免。通過把復制程序的批量讀取范圍固定設置為至少大於或等於寫入的事務長度范圍,避免了第 5 種情況。復制程序批量讀取 binlog 日志事件時,通過標記 SQL 來過濾,避免了循環復制,實現了回環控制。
