Amazon Aurora 的 Serverless 與 Multi-master

Amazon Aurora 推出了兩包玩意,第一包是 Serverless,讓需要人介入的情況更少:「In The Works – Amazon Aurora Serverless」。

在 Serverless 的第一個重點是支援以秒計費:

Today we are launching a preview (sign up now) of Amazon Aurora Serverless. Designed for workloads that are highly variable and subject to rapid change, this new configuration allows you to pay for the database resources you use, on a second-by-second basis.

然後是極為快速的 auto-scaling:

The endpoint is a simple proxy that routes your queries to a rapidly scaled fleet of database resources. This allows your connections to remain intact even as scaling operations take place behind the scenes. Scaling is rapid, with new resources coming online within 5 seconds

這兩個組合起來,讓使用端可以除了在 Amazon EC2 上可以快速 scale 外,後端的資料庫也能 scale 了...

第二個是 Multi-master 架構:「Sign Up for the Preview of Amazon Aurora Multi-Master」。

Amazon Aurora Multi-Master allows you to create multiple read/write master instances across multiple Availability Zones. This enables applications to read and write data to multiple database instances in a cluster, just as you can read across Read Replicas today.

(話說我一直都誤以為 Aurora 是 R/W master...)

Anyway,這個功能不知道怎麼疊上去的... 不笑得會不會有嚴重的 distributed lock issue,反而推薦大家平常都寫到同一台 (像是 PXC 就會這樣)。

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 跳機時的人力操作成本了...

利用 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?

Percona 的 MySQL High Availability 機制比較文

Percona 發了一篇「High-availability options for MySQL, October 2013 update」,比較目前 MySQL 上常見的 High Availability 機制。

包括了五個系統:

  • Percona XtraDB Cluster (PXC)
  • Percona replication manager (PRM)
  • MySQL master HA (MHA)
  • NDB Cluster
  • Shared storage/DRBD

這些都是把 High Availability 做在 MySQL 上,讓前端的程式不需要操心的方式。都是有個固定的 IP address 保證可以讀寫。

這五個方案都不完美,看環境需求而選擇使用。

我一般給的建議還是 Heartbeat + DRBD + InnoDB,這個方法是極為成熟的方法,會遇到的問題網路上都已經討論過了。如果找 Percona 的人支援也是完全沒問題。

在 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

用 Percona Xtrabackup 產生 Slave Server 的方式...

快四年前寫過「XtraBackup:線上備份 InnoDB 的好東西」這篇,但裡面的方法已經不能用了,所以再寫一篇給 Google,之後查資料比較方便...

現在可以參考 Percona 的官方文件「How to setup a slave for replication in 6 simple steps with Xtrabackup」。

先跑一次 full backup:

innobackupex --user=yourDBuser --password=MaGiCiGaM --slave-info /path/to/backupdir

再跑 apply log:(其中的變數自己換掉)

innobackupex --apply-log --use-memory=2G /path/to/backupdir/$TIMESTAMP/

然後整個目錄丟到 slave server 上,用 CHANGE MASTER TO 指令把 master 資訊設好即可 :p

MySQL 平行執行的 Replication...

MySQL Replication – Multi-Threaded Slaves (Parallel Event Execution)」這篇在講 MySQL 5.6 的 multi-threaded replication。

在文章裡提到,在 5.6.3 之前的版本,MySQL replication 都是 single-threaded,所以當 master 可以充分發揮多 CPU 能力時,slave 仍然要一個更新跑完才會跑下一個更新。

舉例來說,假設 master server 上有兩個 thread 在跑:

  • thread 1 正在執行 UPDATE table1 SET foo = 0 WHERE ...; (SQL 1,假定是 CPU bound,需要跑 100 秒)
  • thread 2 正在執行 UPDATE table2 SET bar = 1 WHERE ...; (SQL 2,也假定是 CPU bound,也需要跑 100 秒)

假設 thread 1 先執行完,這時候 slave 就會在跑完的時候收到 SQL 1,然後把資料同步進去。等到 100 秒過去後,再跑 SQL 2,再花 100 秒。這導致了最少 100 秒的 replication lag (master 與 slave 不同步的時間)。

在 master server 執行時會是這樣:

兩個 SQL query 可以同時跑。

到了 slave 時,在 MySQL 5.6.3 之前的 replication 會變成這樣:

可以看到還是得先執行 SQL 1 再執行 SQL 2,所以最長會有 200 秒的 replication lag。

而 5.6.3 之後支援 multi-threaded replication,可以用 slave_parallel_workers 指定平行執行 SQL query 的數量,這讓 master server 與 slave server 之間的 replication lag 降低不少:

在收到同步的 SQL 指令後就可以同時跑,這讓 replication lag 降到 100 秒。

不過還是要提,如果希望把資料同步問題降到最低,那麼 Galera Cluster 可以解的更徹底,不論是寫入的那台 master server,或是其他的 master server (在 Galera Cluster 架構裡都是為 master),一律都是同步執行:

不會有 master server 與 slave server 不同步的問題,可以減少很多 application 層的麻煩...