題幹與適用場景
你負責一個全球 SaaS,單一服務叢集中的資料庫、佇列或發布故障可能影響全部租戶。請設計 cell-based architecture:每個 cell 是可獨立運行的完整系統副本,服務固定的一組租戶;入口根據穩定映射把請求送到目標 cell。
回答需要涵蓋租戶分片、路由目錄、每個 cell 的運算與資料邊界、跨 cell 報表、發布、遷移、容量和災難復原。AWS 的 cell guidance 將 cell 描述為獨立副本,並把 user-to-cell mapping 放在高可用儲存中;bulkhead 指南強調路由層應按 partition key 分發請求並保持單一入口。
面試官考察點
- 是否先定義故障影響範圍、租戶一致性和可接受的降級。
- 是否把 cell 設計成真正獨立的故障域,而不是只複製無狀態服務。
- 是否識別路由目錄、控制面、共享依賴和跨 cell 查詢的新故障點。
- 是否說明新增 cell、重平衡和租戶遷移的可回滾步驟。
- 是否用容量、錯誤率和跨 cell 依賴指標驗證 blast radius。
系統設計面試資料把 cell-based architecture 歸為大規模系統的隔離模式。強回答會解釋它何時值得承擔重複基礎設施和運維複雜度,而不是把 cell 當成微服務的同義詞。
回答前需要澄清的問題
- 故障目標是單一租戶、一個 cell、一個可用區還是整個區域?
- 租戶之間是否允許共享資料、全域搜尋或跨租戶聚合?
- 哪些操作必須線性一致,哪些報表可以延遲或最終一致?
- 遷移期間是否允許短暫唯讀?是否有合規的地域駐留限制?
- 目標可用性、租戶數量、增長速度、單 cell 容量和發布頻率是多少?
30 秒回答框架
我會先按穩定租戶鍵把流量分配到固定 cell,每個 cell 擁有獨立的運算、佇列、快取和主資料儲存;全域控制面只維護版本、容量和映射。入口路由讀取高可用目錄,故障時只摘除受影響 cell。跨 cell 報表走非同步彙總,不讓查詢重新引入共享資料庫。新增 cell、遷移和發布都採用小批次、可觀測、可回滾的流程,並用 cell 級 SLO 驗證故障邊界。
分步驟深入解答
第一步:定義 cell 邊界與故障假設
把一個 cell 定義為可獨立部署和復原的完整副本:API、工作佇列、快取、資料庫、物件儲存前綴和監控。共享的身分、計費或設定服務要明確可接受的故障範圍;如果共享控制面掛掉會阻斷所有 cell,它就不是資料面完全隔離。
第二步:選擇分片鍵與路由目錄
以 tenant_id 作為穩定 partition key,目錄記錄 tenant 到 cell、版本、遷移狀態和容量。路由層先從本地快取讀取,再從高可用目錄刷新;更新採用版本號和租約,防止遷移時舊路由把寫請求送到兩個 cell。客戶端只看到一個網域,路由層負責重試邊界。
第三步:建立 cell 內資料平面
每個 cell 有獨立主庫和訊息佇列,租戶資料不跨 cell 直接寫。讀副本、快取和物件儲存按 cell 命名,備份也保留 cell 元資料。需要全域設定時使用唯讀快照或版本化發布,禁止把高頻請求回退到一個全球共享資料庫。
第四步:處理跨 cell 查詢
產品報表透過每個 cell 的變更流生成彙總表,再由全域分析層讀取。查詢必須標記資料時間和遺漏 cell,不能假設即時完整。需要強一致的跨租戶操作應縮小範圍、改成非同步工作流,或明確它會犧牲 cell 隔離;不要在請求路徑上做跨 cell 兩階段提交。
第五步:設計故障與降級路徑
健康檢查分為 cell 內依賴、路由可達性和業務正確性。某 cell 失效時,路由目錄把它標記為 draining,新請求停止進入;唯讀快取或非同步任務可按業務允許降級。不要讓租戶自動漂移到任意 cell,除非資料複製、冪等和權限邊界已驗證,否則故障轉移會製造重複寫入。
第六步:新增 cell 與容量重平衡
以基礎設施範本建立空 cell,先執行合成流量和影子讀,再接入少量租戶。容量指標包括 CPU、資料庫連線、佇列延遲、儲存增長和每租戶成本。重平衡先凍結映射版本,複製資料並校驗計數,短暫切換寫入,再觀察新舊 cell 的一致性,失敗則回退映射而不是刪除舊資料。
第七步:發布與版本治理
發布控制面、cell 範本和業務版本分開。先在一個 cell 做 canary,再按 cell 擴大;路由目錄保留相容窗口,避免新版本寫入舊版本無法讀取的欄位。跨 cell 的版本分布和錯誤率必須可見,不能因為全域平均成功率正常就忽略一個壞版本。
第八步:驗證 blast radius 與運維成本
故障演練應注入單一 cell 資料庫、佇列、路由目錄和發布錯誤,確認影響只覆蓋預期租戶。指標包括每 cell 可用性、錯誤預算、跨 cell 請求比例、遷移回滾時間、共享控制面依賴和容量餘量。若 cell 數量太小無法隔離,或重複基礎設施成本超過可靠性收益,應回到分區或 bulkhead 的較簡單方案。
高品質示範回答
我會把 tenant_id 映射到固定 cell,每個 cell 獨立運行 API、佇列、快取和主資料儲存,控制面只維護版本、容量和映射。入口路由以單一網域提供服務,讀取帶版本的高可用目錄;故障 cell 進入 draining,避免把未驗證的資料寫入其他 cell。跨 cell 報表透過變更流非同步彙總,遷移採用複製、校驗、短暫切換和可回滾映射。用 cell 級 SLO、共享依賴占比、遷移回滾時間和故障演練證明 blast radius;當隔離收益小於複製和運維成本時,選擇更簡單的 bulkhead。
常見錯誤
- 只複製無狀態服務 → 共享資料庫仍是單點 → 畫清每個 cell 的資料和佇列邊界。
- 讓租戶故障時隨機漂移 → 產生重複寫入或權限錯配 → 先驗證複製、冪等和路由版本。
- 在請求路徑跨 cell 聚合 → 新的全球故障域 → 用非同步彙總和資料時間標記。
- 只有全域健康檢查 → 壞 cell 被平均值掩蓋 → 記錄 cell 級 SLO 和版本分布。
- 遷移直接改路由 → 新舊寫入並存 → 使用映射版本、複製校驗和可回滾切換。
- 每個依賴都做獨立 cell → 成本和運維失控 → 先量化 blast radius 與容量收益。
追問及應對
路由目錄掛了怎麼辦?
保留帶版本的本地快取和唯讀快照,限制映射變更,並讓既有租戶繼續存取原 cell。目錄恢復前不做大規模重平衡。
跨 cell 的管理員報表必須即時怎麼辦?
先確認「即時」允許的延遲和缺失語義。若必須強一致,就縮小操作範圍或接受更大的共享故障域;常規報表應使用帶時間戳的非同步彙總。
單一 cell 容量不足如何遷移?
先複製並校驗資料,發布新映射版本,短暫協調寫入,再逐步放量。遷移期間保留舊 cell,發現差異時回滾映射。
一個版本只在部分 cell 上線安全嗎?
可以,但必須有相容 schema、版本可觀測性和明確的放量順序。全域成功率不能替代逐 cell 的錯誤預算。
如何證明故障沒有擴散?
演練 cell 內資料庫、佇列、路由和發布故障,記錄受影響租戶集合、跨 cell 請求、復原時間和共享依賴呼叫。
什麼時候不用 cell-based architecture?
租戶量小、故障成本低或資料強一致跨租戶操作占主導時,cell 的重複資源和遷移複雜度可能不值得。
cell 之間如何共享身分與計費?
把共享服務限制在低頻控制面,快取唯讀結果並定義降級;計費寫入要有冪等鍵和補償流程,避免共享服務故障擴散到所有資料面。