分庫分表不是大流量架構的第一步,而是最後一步。太多團隊在壓力測試還沒跑過、快取還沒鋪好的時候,就先把資料庫切成八份,然後花接下來半年時間處理跨分片 join、分散式交易與資料遷移。這種順序錯了,不管砸多少人力都補不回來。
大流量架構其實是一道有順序的題目。做對前面幾步,後面的複雜度往往可以省掉一大半。
先把便宜的做完,再談貴的
處理高併發的成本,從低到高大致是這樣:CDN 與靜態資源 → 應用層快取 → 資料庫讀取快取 → 非同步化 → 水平擴展無狀態服務 → 讀寫分離 → 資料分片。越往後,運維與心智負擔越重。
CDN 與靜態資源:這是投報率最高的一層。把圖片、JS、CSS、甚至部分 API 回應丟到 CDN 邊緣節點,能吃掉相當比例的請求。對電商網站來說,商品圖與首頁 banner 是最容易被忽略的流量大戶。
快取策略:這裡最常見的錯誤不是「沒用 Redis」,而是「什麼都塞進 Redis」。要問三個問題:這份資料多常變?讀寫比是多少?失效了會怎樣?熱門商品列表適合快取幾分鐘、寫入穿透用 write-through,庫存這種強一致資料就不該直接快取,而是用 Redis 做原子遞減再定期回寫。
無狀態服務:Session 放在 Redis 或 JWT,應用本身不留任何本地狀態,才能無腦水平擴展。任何一個放在記憶體的變數、任何一個寫到本地磁碟的檔案,都是未來的雷。
訊息佇列:把「使用者不需要當下知道結果」的動作丟進 Kafka 或 RabbitMQ。寄信、產報表、更新推薦、寫日誌,這些通通不該擋在同步請求路徑上。假設一個下單流程原本要做八件事,能非同步化到四件,前端 P99 延遲就能顯著下降。
分片是最後手段,可觀測性是全程手段
真的走到需要分庫分表的時候,先問自己:主庫 CPU 是不是真的壓到極限?還是只是慢查詢沒調?索引是不是漏了?讀取有沒有先分流到 replica?很多時候,一顆升級版的雲端資料庫加上讀寫分離,就能撐住多一個數量級的流量,而且不需要處理跨分片的一致性問題。
如果真的要分片,選 shard key 時要優先避開三件事:熱點集中、跨分片查詢頻繁、需要全域唯一遞增 ID。以電商為例,用 user_id 分片通常比 order_id 好,因為使用者的多數查詢都圍繞自己的訂單。
最後也是最容易被跳過的:可觀測性。沒有 metrics、traces、logs 這三件套,任何優化都是猜的。至少要能回答:現在哪個 endpoint 最慢?慢在資料庫還是外部 API?P99 是多少?錯誤率是不是在爬?OpenTelemetry 加上任意一套後端(Grafana、Datadog、SigNoz 都可以)是現在的合理起點,不需要一開始就上最貴的方案。
我們的觀察
協和數位在跟客戶討論架構升級時,通常會先花時間看現有系統的監控數據與慢查詢日誌,而不是先開架構圖。因為大流量架構的真正瓶頸,八成藏在一兩個具體的查詢、一段沒設 TTL 的快取、或一個同步呼叫的第三方 API 裡面。把這些先揪出來,往往比重寫整套服務便宜太多。順序對了,錢才會花在刀口上。
