在 MySQL 上遇到 Replication Lag 的解法

看到 Percona 的 blog 上寫了一篇 MySQL 遇到 replication lag 時要怎麼解決:「MySQL High Availability: Stale Reads and How to Fix Them」,另外在留言也有人提到 Booking.com 的解法:「How Booking.com avoids and deals with replication lag」。

在業務成長到單台 MySQL server 不夠用的情況下,最簡單的擴充方式是架設 slave server,然後把應用程式裡讀取的部份導到 slave 上 (也就是 R/W split),但因為 MySQL 的 replication 是非同步的,所以有可能會發生在 master 寫入資料後 slave 還讀不到剛剛寫的資料,也就是 replication lag。

這就大概有幾種作法,一種是當發現 lag 時就回 master 讀,但通常這都會造成 master 過載... 所以另外一種改善的作法是發現 lag 時就換其他 slave 看看,但這個方法就不保證讀的到東西,因為有可能所有的 slave 都 lag。

以前遇到的時候是拆情境,預設還是 R/W split,但敏感性的資料處理以及金流相關的資料就全部都走 master。

不過文章裡的解法更一般性,在寫入時多寫一份資料,然後在 slave 等這組資料出現。唯一的缺點就是要 GC 把多寫的資料清掉...

同樣的想法,其實可以讓 MySQL 在 commit 時直接提供給 binlog 或 GTID 的資訊,然後在 slave 等待這組 binlog 或 GTID 被執行。

看起來算是很不錯的解法,不知道各家 framework 對這些方式的支援度如何...

Amazon DynamoDB 跨區 Replication 以及備份

Amazon DynamoDB 實做了全球性的 replication,以及備份功能:「Amazon DynamoDB Update – Global Tables and On-Demand Backup」。

跨區 replication 的功能讓每個 region 都可以存取當地機房的 DynamoDB:

Global Tables – You can now create tables that are automatically replicated across two or more AWS Regions, with full support for multi-master writes, with a couple of clicks. This gives you the ability to build fast, massively scaled applications for a global user base without having to manage the replication process.

這有點類似 GoogleCloud Spanner 在前陣子也推出全球性服務,但 DynamoDB 提供的比較偏向 NoSQL 而不是 RDBMS。

另外一個限制是跨區同步是 async,會有 replication lag 的問題:

Updates are propagated to other Regions asynchronously via DynamoDB Streams and are typically complete within one second (you can track this using the new ReplicationLatency and PendingReplicationCount metrics).

不過如果是這樣的機制,conflict 的問題不知道怎麼解決... 文章裡面沒看到。

然後目前支援的區域還是有限:

Global Tables are available in the US East (Ohio), US East (N. Virginia), US West (Oregon), EU (Ireland), and EU (Frankfurt) Regions today, with more Regions in the works for 2018.

另外一個是備份與還原機制,有這樣的功能對很多計畫方便不少:

On-Demand Backup – You can now create full backups of your DynamoDB tables with a single click, and with zero impact on performance or availability. Your application remains online and runs at full speed. Backups are suitable for long-term retention and archival, and can help you to comply with regulatory requirements.

而備份還原機制是陸陸續續開放的,區域也有限:

We are rolling this new feature out on an account-by-account basis as quickly as possible, with initial availability in the US East (Northern Virginia), US East (Ohio), US West (Oregon), and EU (Ireland) Regions.

AWS Direct Connect 可以多條線路綁在一起用了

AWS Direct Connect 支援 Link Aggregation Group (LAG),將多條線路綁在一起了:「AWS Direct Connect enables Link Aggregation Group for additional AWS regions」。

We are excited to announce support for 1G and 10G Link Aggregation Groups (LAG). Customers in AWS GovCloud (US), Europe (Frankfurt), Europe (London), Europe (Ireland), Asia Pacific (Tokyo), Asia Pacific (Singapore), Asia Pacific (Sydney) regions can start using LAG to link existing connections on the same AWS device, or request new connections.

主要還是對於超大量的用戶會變方便 (都是使用 10Gbps 線路接上去的使用者),尤其是 load balancing 這塊會好做不少。

多條 1Gbps 的當然也是有幫助,不過剛好只會落在一個微妙的範圍 (到 8Gbps 的時候,直接換 10Gbps 成本說不定其實差不多...)。

Amazon Aurora 支援 Reader Endpoint

Amazon Aurora 支援 Reader Endpoint,讓讀的部份可以打散掉:「New Reader Endpoint for Amazon Aurora – Load Balancing & Higher Availability」。

讀的部份比較容易 scale (常見的方式是透過 replication 做到),而現在很多 database framework (包括各類的 ORM framework) 都支援讀寫分離,這個支援對於系統的 scale 來說幫忙頗大。

不過不知道會不會有 replication lag 的問題,我猜是會有...

Percona 將辦 Webinar 說明資料庫讀寫分離時的處理...

MySQL replication 通常是資料庫擴充的第一步,因為架設很簡單。但一般 MySQL replication 的讀寫必須分開 (寫入只能在 master)。

在「Webinar on Read/Write Splitting with PHP」看到 Percona 下星期會辦 Webinar,說明在 MySQL replication 架構下要如何處理讀寫分離。

看起來包括對 replication lag 時的處理 (slave 因為各種原因,導致跟不上 master),有興趣的人可以去報名聽聽看... 雖然是講 PHP,但這個問題在其他的語言也會遇到,聽觀念也應該有幫助。

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 層的麻煩...

Wine 玩 Diablo III 音樂會頓的問題...

這幾天用 WineDiablo III,有時聲音會狂 lag,關掉 Diablo III 後重跑還是一樣,要重開機才會恢復...

仔細看 Wine 丟出來的訊息,發現訊息內有給這個網頁:「winepulse in ubuntu wine ppa」,其中提到 1.5.3 以後的 ppa 版本 (寫這篇文章的時候是 1.5.4) 可以在啟動 Wine 時加上環境變數 WINENOPULSE=1 解決聲音的問題。

目前測起來是正常了,不知道還會不會有其他問題要解...