跳至主要内容

為什麼不要直連

五個代價,每一個都是已經在某處發生過的事

直連不是因為老派才不好,是因為五個具體後果。而每一個當成場景來看,都比當成原則來看好懂。

01 · schema 成了事實上的對外 API​

一個叫 status 的欄位有四種值。現在需要第五種。擁有它的團隊 grep 過自己的程式碼、改完、上線 —— 然後另一個部門一支報表工作裡寫死的 WHERE status IN (...),安靜地少算了五分之一的訂單。一個月沒人發現。

團隊從這件事學到的不是「以後要協調好」,而是**「那個欄位永遠不要動」**。這樣來個幾次,schema 就被恐懼凍住了,而要加一個欄位,最快的方法變成把現有欄位拿來一位多用。

02 · 授權的單位是資料表,稽核記的是連線​

一條授權寫的是 SELECT on orders。它說不出哪些列、為了什麼、代表誰。當稽核問題來了 —— 14 號是誰讀了這位客戶的訂單 —— 拿得出來的答案是一條來自某台應用伺服器的連線,而那條連線是那天該應用服務過的所有請求共用的。

這正是契約補上的缺口:擁有者服務知道呼叫方、知道操作、知道是哪一列,三件事都記得下來。擁有者怎麼知道呼叫方是誰 —— 一個它在每個請求上都驗證的服務身分 —— 寫在契約頁的「呼叫方身分」一節。

03 · 耦合是隱形的​

動一張表之前,誠實的問題是「誰在讀?」。在直連的世界裡沒有答案 —— 只有一份「持有這條授權的憑證清單」,那是誰有資格讀,不是誰真的在讀。規劃一次變更變成到處問人,然後祈禱知道的那個人沒有請假。

這也是為什麼擁有權是從資料庫側盤點起,而不是發問卷:問卷記下的是各團隊記得什麼,而這個環境的實況與他們記得什麼無關。

04 · 連線數隨實例數成長​

每個應用副本各開自己的連線池。六個應用各十個副本就是六十個連線池,全部照尖峰配置、多數時間閒置,而且全部算在同一個 max_connections 上。

現在副本數是固定的,因為應用跑在手工建的 VM 上。路線圖項目 26 要把它們搬上 Kubernetes —— 那件事的重點就是副本數隨負載變動,而資料庫正是吸收不了這種變動的東西。

05 · 它擋住底下的平台​

路線圖上有兩個項目在等這件事:

  • 項目 06 — Database IaC 與 DBaaS。 要改複製拓樸或 failover 目標,前提是知道所有客戶端。讀方不明,這種變更沒有人會簽。
  • 項目 27 — 多站點資料倉儲。 一個站點要能獨立,前提是讀它資料的東西是已知且在地的。一個沒被記錄的跨站讀方,會把單站故障變成全公司故障。

這兩件事都不是靠「多加 API」解決的。兩件事都是靠讀方變成可知解決的 —— 而那是同一個前提。