核心定位

SaaS 多租戶讓你用一套程式碼同時服務多個企業客戶,每個客戶(租戶)只能看到自己的資料,彼此完全隔離。無論是做垂直 SaaS 產品還是企業內部多子公司管理,這都是不可或缺的能力。

兩種方案:欄位隔離(輕量級,適合中小規模)和資料庫隔離(物理隔離,適合大規模 SaaS)。


適合什麼樣的使用者

場景推薦方案原因
SaaS 創業初期欄位隔離運維簡單,一臺資料庫搞定
大型 SaaS 平臺資料庫隔離物理隔離,安全性高,可獨立備份
企業內部多公司欄位隔離公司數量有限,邏輯隔離足夠
金融/醫療等強合規行業資料庫隔離資料必須物理隔離

兩種方案對比

graph TB subgraph COLUMN["方案一:欄位隔離 COLUMN 模式"] direction TB C1["所有租戶共享
同一資料庫同一套表"] C2["每張表新增
tenant_id 欄位"] C3["SQL 攔截器
自動拼接 WHERE tenant_id = ?"] C4["優點:運維簡單、資源利用率高
缺點:邏輯隔離,安全性一般"] C1 --> C2 --> C3 --> C4 end subgraph DATASOURCE["方案二:資料庫隔離 DATASOURCE 模式"] direction TB D1["主庫:共享表
使用者/選單/配置/租戶資訊"] D2["租戶庫 A:業務表"] D3["租戶庫 B:業務表"] D4["租戶庫 C:業務表"] D5["優點:物理隔離、安全性高、可獨立備份
缺點:運維複雜、資源利用率低"] D1 --> D2 D1 --> D3 D1 --> D4 D2 & D3 & D4 --> D5 end

詳細對比

維度欄位隔離(COLUMN)資料庫隔離(DATASOURCE)
隔離級別邏輯隔離物理隔離
安全性中等(依賴 SQL 攔截)高(資料庫級隔離)
資源利用率高(共享連線池)低(每租戶獨立連線)
運維複雜度低(單庫運維)高(多庫運維)
擴充套件性受限於單庫效能可水平擴充套件
資料備份需要按 tenant_id 篩選每個租戶獨立備份
適用規模百級租戶千級/萬級租戶
技術實現MyBatis Plus 攔截器dynamic-datasource

欄位隔離實現原理

sequenceDiagram participant U as 使用者(租戶A) participant APP as 應用層 participant INTERCEPTOR as SQL 攔截器 participant DB as 共享資料庫 U->>APP: 查詢客戶列表 APP->>INTERCEPTOR: SELECT * FROM crm_customer INTERCEPTOR->>INTERCEPTOR: 自動拼接 tenant_id = 'A' INTERCEPTOR->>DB: SELECT * FROM crm_customer
WHERE tenant_id = 'A' DB-->>APP: 只返回租戶A的資料 APP-->>U: 顯示客戶列表

核心機制:透過 MyBatis Plus 的多租戶外掛,在執行任何 SQL 前自動新增 tenant_id 條件,對業務程式碼完全透明。


資料庫隔離實現原理

基於 dynamic-datasource 動態資料來源,請求進入時根據當前租戶 ID 切換到對應的資料來源:

spring:
  datasource:
    dynamic:
      primary: master  # 主庫(共享表)
      datasource:
        master:        # 主庫配置
          url: jdbc:mysql://localhost:3306/ruoyi_master
        tenant_1:      # 租戶1的獨立資料庫
          url: jdbc:mysql://localhost:3306/ruoyi_tenant_1
        tenant_2:      # 租戶2的獨立資料庫
          url: jdbc:mysql://localhost:3306/ruoyi_tenant_2

租戶套餐管理

graph LR PACKAGE1["基礎版套餐
系統管理 + 基礎功能"] PACKAGE2["專業版套餐
基礎版 + CRM + ERP"] PACKAGE3["旗艦版套餐
全部功能"] 租戶A["租戶 A"] --> PACKAGE1 租戶B["租戶 B"] --> PACKAGE2 租戶C["租戶 C"] --> PACKAGE3

每個租戶可以繫結一個套餐,套餐定義了該租戶可見的選單和可用功能。支援套餐到期自動禁用。

docs