Percona XtraDB Cluster 5.6 與 GTIDs 的結合

Percona 的 Fernando Laudares 在「How to setup a PXC cluster with GTIDs (and have async slaves replicating from it!)」這篇裡提到了 Percona XtraDB Cluster 5.6 與 GTIDs 的配合方式。

傳統的 replication 的 binlog 的表示方式是 filename + position,這個是大家已經很熟悉的方式。

digraph {
    M1 [label="Master 1"];
    M2 [label="Master 2"];

    S1 [label="Slave 1"];
    S2 [label="Slave 2"];
    S3 [label="Slave 3"];
    S4 [label="Slave 4"];

    { rank=same; M1; M2; };

    { rank=same; S1; S2; S3; S4; };
    S1 -> S2 -> S3-> S4 [style=invis];

    M1 -> M2;
    M2 -> M1;

    M1 -> {S1, S2, S3, S4};
    M2 -> {S1, S2, S3, S4} [color=gray];
}

優點是很簡單 (很好理解,也很容易設定管理),但缺點是 Slave 的 Master 跳動時 (從 Master 1 跳到 Master 2),Slave 可能會漏資料。

原因是出自於 MMM 之類的工具無法知道 Master 1 最後一筆寫入的資料對應到 Master 2 的哪個 binlog 位置。

MySQL 5.6 之後多了新的模式,叫做 GTIDs (Global Transaction IDs),把本來 binlog 的 filename + position 改良一下,變成 source_id + transaction_id 的形式。

source_id 是每台機器固定的值,目前是用 UUID 代表,而 transaction_id 則是遞增的流水號。所以也很好理解:「source_id 這台機器的第 n 個 transaction」。

這樣就可以多出很多偵測機制,降低問題發生的機率。

而 PXC 5.6 在這個領域則是因為已經有了自己的 cluster 機制,所以整個 cluster 會共用一組 UUID。這樣就可以避免混用機制而產生複雜的問題。

所以就變成三台 Master 互相切換 (通常 PXC 都是三台以上的奇數機器):

或是其中兩台互相切換 (第三台只跑 garbd 而沒有實際資料時):

我們家只剩下一組 cluster 是 PXC 5.5 (最大的一組),其他都是 PXC 5.6 了。應該要找人 deploy 這個機制降低 Master 跳機時的人力操作成本了...

MySQL 的 Parallel Replication

Multithreaded Replication to the Rescue」這篇提到了 Replication 的 Parallel Worker 機制。

作者給了平行的數量對 replication lag 的影響:

可以看得出來 Parallel Worker 機制對 Replication Lag 改善頗大,不過作者在 comment 提到中雷了:「MTS breaks in after restart」。

對於還在使用 traditional master-slave 架構的人可以參考看看。

利用 pt-online-schema-change 同步 master 與 slave 的資料

在「Syncing MySQL slave table with pt-online-schema-change」這篇看到 master 與 slave 的資料不同步時,強制性同步的方法:

pt-online-schema-change --alter 'ENGINE=INNODB' D=dbname,t=tblname

由於 pt-online-schema-change 的作法是建一個新的表格,然後把舊表格的資料寫過去,而這些行為會被 replicate 到新機器上,於是就同步了...

這招有趣 XDDD

AWS 提供跨區的 MySQL Read Replica...

Amazon RDS 將提供跨區的 MySQL read replication。看起來是針對 5.6+ 的版本提供這個功能...

有兩篇官方文章,一篇是 CTO 發了一篇「Expanding the Cloud: Enabling Globally Distributed Applications and Diaster Recovery」,另外一篇是官方網誌上的「Cross-Region Read Replicas for Amazon RDS for MySQL」。

用圖表示比較容易懂:

在 US-East 建立 MySQL master,另外在 EU 與 Tokyo 建立 slave replication。不知道中間的 traffic 有沒有過 IPSec 或是 SSL?

Amazon RDS 可以直接產生 Read Replica Replication 了...

以往要在 Amazon RDS 產生 Read Replica Replication 需要複雜的 snapshot 處理,但現在 AWS 直接提供這個功能了,而且可以同時生很多台:「New Read Replica Capabilities for Amazon RDS」。

這有多重要呢?以前因應流量瞬間爆增時的方式是增加 web server,並且利用 cache (可能是 memcached) 降低對後端的 query 數量。但因為引入 cache,平常就得處理 cache invalidate 的問題。

而這個方式平常只要處理讀寫分離就可以了。當量爆增時除了 web server 增加,直接增加後端的 RDS server (Read Replica Replication),甚至可以分層:

以目前的步調來看,之後有可能會推出 Master-Master 的 HA 架構?

Update:照 comment 提到的,Multi-AZ 本身就是 HA 架構了...

Percona 的 Crash-resistant replication

前幾天 Percona 寫了篇文章說明自家專有的 Crash-resistant replication (用在 Percona Server 5.1 與 5.5):「Crash-resistant replication: How to avoid MySQL replication errors」。

這是 async replication 用在 slave server crash 時的保護機制。

當 slave 更新資料後,會更新 relay log 寫下「目前 apply 到哪個位置」(預設值是 relay-log.info),也就可以依照這個資訊計算出 replication lag 的時間。在 mytop 裡看到的 Delay 欄位就是由此算出來的。

但當 MySQL 寫入後,但 relay-log.info 還沒更新時當掉,會造成下次啟動時重複 apply 同一筆資料。

而 Crash-resistant replication 就是把這個資訊寫到 transaction 內,避免這個問題。

也因此這個功能只有 InnoDB 類的 Engine 才有用,MyISAM 仍然是不受 Crash-resistant replication 保護的。

要打開這個功能也很簡單,只要 my.cnf 設起來就好了,設定說明可以參考原文。

在 Percona XtraDB Cluster 裡使用 async replication 時人工 failover 的方式...

在使用 Galera Cluster 時還是可以架設一般的 slave server (Percona XtraDB Cluster 則是 Percona 對 Galera Cluster 的封裝),像是這樣的架構:

其中 node{1,2} 為 cluster,node3 則是傳統的 async replication,來源的 master 為 node1。

當 node1 掛掉時,我們沒辦法自動將 node3 的 master 從 node1 改指到 node2,因為 binlog 的位置不一定正確。

在「Changing an async slave of a PXC cluster to a new Master」則是提供如何人工用最簡單的方式介入。

主要是靠 Galera Cluster 會在 binlog 內寫入 Xid 這個值,這個值可以在 global status 內的 wsrep_last_committed 看到。因為這個值在全 cluster 都是同步的,就可以拿來人工尋找 binlog 位置後手動下 CHANGE MASTER TO,而不用 pt-table-sync 同步修老半天...

而且邏輯被整理出來以後,就有機會寫成程式自動化... 這算是一個不錯的開頭 :p

MySQL 5.6 的 GTID...

看到 Percona 的人在討論 MySQL 5.6 的 GTID (Global Transaction ID) 功能,剛剛就實際到 AWS 上開了兩台 m1.large 測試:「How to create/restore a slave using GTID replication in MySQL 5.6」。

要測試 GTID,因為剛出來沒多久,沒有多少文件可以看。MySQL 官方的「Replication with Global Transaction Identifiers」是必讀的文件。查 MySQL 官方文件時可以發現 5.6.9 (RC) 到 5.6.10 (GA) 其實還是改了不少變數名稱,如果在網路上找舊文章照抄是不會動的...

先提結論,Galera Cluster 畢竟出來很久了,成熟度比 GTID 高,建議現在先觀望一陣子,至少等 best practice 出來後再進場測試...

之前的 MySQL replication 有很多方法可以在不停機,或是停的時間很短的情況下把第一份 slave 資料與 replication 資訊生出來,舉例來說:

  • 系統如果用 InnoDB,可以用 Percona Xtrabackup 拉出。
  • 系統如果用 XFS + LVM,可以用 FLUSH TABLES WITH READ LOCK + XFS freeze + snapshot 功能拉出。
  • 甚至直接用空的 slave 跑 pt-table-sync...

但目前 MySQL 官方對 GTID 給的方式是 read only + mysqldump,這就算用 xtrabackup 也應該快不到哪吧... 這幾個月應該會一直有文章出現,裡面應該會有偷吃步的方法,看到再來測試看看 :o

跳過 MySQL replication 失敗的方法...

MySQL replication 發生錯誤後,需要一邊 skip replication error,一邊跑 pt-table-sync 強制資料庫同步:

while true; do ( echo 'SET GLOBAL sql_slave_skip_counter = 1; START SLAVE;' | mysql -h $1 ) || sleep 1; done

那個 sleep 1 的設計是用在「如果 replication 正常,停一下再跑一次」的前提下而設計的;如果不需要的話拿掉也是 okay 的。

要注意,能這樣跑的前提是 max_connect_errors 要開超大,我是設成 max_connect_errors = 4294967295

Stripe 發表了將 MongoDB 資料倒到 PostgreSQL 的工具:MoSQL

Stripe 是家電子付款的新創公司,相較於既有的電子付款機制 (像是 PayPal),Stripe 所提供的工具與介面對開發者與使用者非常友善。

昨天 Stripe 推出了即時將 MongoDB 的資料倒到 PostgreSQL 的工具 MoSQL:「Announcing MoSQL」。

據官方說法,要撈資料的時候用 SQL 比較方便,而且每個人都懂 SQL,所以他們開發了 MoSQL:

The thing is, we also love SQL. We love the ease of doing ad-hoc data analysis over small-to-mid-size datasets in SQL. We love doing JOINs to pull together reports summarizing properties across multiple datasets. We love the fact that virtually every employee we hire already knows SQL and is comfortable using it to ask and answer questions about data.

由於 PostgreSQL 9.2 支援 JSON 資料結構,感覺很像是要逃離 MongoDB 的工具啊... 雖然官方都不承認 XD