Rails 實現 db 讀寫分離也是今天的主題。

相信很多過電商的朋友, 都遇到過 限時搶購 或是 限量商品 的情況
大量的請求, 可能會導致網站暫時掛掉, 而讓消費者跑掉或頭數的情況。
所以在這種活動前, 可能就是 無限制擴充 Server ($$$)
但其實這大量的請求中, 有很大的請求來至 讀取(SELECT), 實際真的寫入(INSERT、UPDATE、DELETE) db 一定會比 讀取(SELECT) 來得少。

那其實我們可以往 讀寫分離 這個方向去解決。
剛好 Rails 6.1 就支援了 Multiple Databases with Active Record
但今天的範例會使用 Rails 7

要如何設置你的 database.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
database.yml

default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: your_password
socket: /tmp/mysql.sock

development:
primary: # master db
<<: *default
database: primary_db
primary_replica: # slave db
<<: *default
database: primary_db_replica
replica: true

其中 replica 複製品的意思。

primarymaster 主要負責 寫入, e.g., POST、PUT、PATCH、DELETE
primary_replicaslave 主要負責 讀取, e.g., GET, HEAD

Create an abstract class for your model

1
2
3
4
5
6
7
# frozen_string_literal: true

class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true

connects_to database: { writing: :primary, reading: :primary_replica }
end

由此可見, 我們分別設定了 的 db 分別指向哪個。
其實這樣就已經設定好, 我們的讀寫分離了。
寫入 master 的時候會同時複製一份到你的 replica 上。

為了驗證讀寫分離, 對 db 的請求有多少, 所以我在 GCP 上, 使用了 Cloud DBReplicas 來驗證
先驗證資料是否有同步好了!

這是 master 目前的樣子
test_db1

這是 replica 目前的樣子
test_db_replica1

我做了第一次 create
first_create

master 有存入這筆資料
test_db2

同時 replica 也同步了
test_db_replica2

有此可見資料是同步的。
但因為服務要錢, 所以真的要測試大流量就先止步了

總結

雖然這樣就做好簡單的設定, 但其實還有非常多的進階設定可以做, 水也很深。
例如:

  1. 加入 HA 連監聽 db 是否活著, 發現 master 掛掉了, 自動把 replica 轉成 master,
    就不會有資料不同步的問題
  2. 當寫入後複製資料時有些許時間差
  3. 多 db 多 replica 的存在, 兩個不同資料庫, 但 table 有關連的時候,
  4. 在特定的 action 只能做 , 只要寫入就噴錯, 等等。

在現在這種電商時代, 如何把使用者留著, 甚至在大流量時不暫時掛掉, 都是相當重要的
包括 redis 也可以做到這種架構!

以上為心得分享, 因為偏架構的部分, 還是第一次寫這種文章, 還希望有錯的地方可以指教!

redis架構
文章參考
文章參考

-W