2. 多租户配置模型设计
配置中心的核心难点不在“存配置”,而在“同一份配置如何被不同租户、不同应用、不同环境正确解析”。如果数据模型只设计成一张 key-value 表,很快就会遇到三个问题:租户之间数据串扰、环境之间配置覆盖混乱、公共配置无法复用。因此,多租户配置模型必须先把领域对象和它们之间的关系定义清楚,再谈存储与缓存。
一、六个核心领域对象
一个可落地的多租户配置模型通常包含六个核心对象:租户(Tenant)、应用(Application)、环境(Environment)、配置项(ConfigItem)、配置版本(ConfigVersion)、继承关系(Inheritance)。它们不是并列的,而是有明确的归属和层级。
- 租户:数据隔离的最高边界,拥有独立的命名空间、配额和权限体系。租户之间默认不可见。
- 应用:隶属于某个租户,代表一个可独立部署的服务或产品线,如
order-service、payment-gateway。 - 环境:隶属于应用,常见取值为
dev、test、staging、prod,用于隔离同一应用在不同生命周期阶段的配置。 - 配置项:最小配置单元,由
key、value、type、description等字段构成,归属于某个“应用 + 环境”组合。 - 配置版本:一次发布产生的不可变快照,包含版本号、发布时间、发布人、变更 diff,用于回滚和审计。
- 继承关系:描述配置项之间的复用路径,使子级可以覆盖父级,而不必重复定义。
二、继承关系:模型中最容易出错的部分
继承不是简单的“父子复制”,而是一条解析链。推荐采用“租户公共 → 应用公共 → 环境专属 → 实例覆盖”的四层继承模型。解析时从最具体的一层向上查找,遇到第一个命中的 key 即停止,这就是“就近覆盖”原则。
例如,租户 t-acme 下应用 order-service 的 prod 环境需要读取 db.pool.size。解析顺序为:
1. 实例级覆盖 tenant=t-acme / app=order-service / env=prod / instance=i-01
2. 环境级配置 tenant=t-acme / app=order-service / env=prod
3. 应用级公共 tenant=t-acme / app=order-service / env=*
4. 租户级公共 tenant=t-acme / app=* / env=*
若四层都未命中,则返回“未配置”错误,而不是静默使用空值。这一点必须在领域模型中显式定义,否则线上会出现难以排查的默认值问题。
三、数据模型与领域建模的对应
领域模型建议采用聚合根设计:租户是聚合根,应用、环境、配置项都通过租户外键约束;配置版本是独立聚合,因为它一旦发布就不可变,只追加不修改。配置项的每次变更不直接改原记录,而是生成一条新的版本记录,当前生效版本通过指针指向最新已发布版本。
下面这张图展示了六个对象之间的归属、继承与版本关系,是本节最需要建立的整体认知。
四、关键字段与约束
为了让模型可落地,每个对象至少需要以下字段和约束。这里给出的是示例性设计,实际项目可按需裁剪。
| 对象 | 关键字段 | 约束 |
|---|---|---|
| Tenant | tenant_id, name, status, quota | tenant_id 全局唯一 |
| Application | app_id, tenant_id, name, owner | (tenant_id, name) 唯一 |
| Environment | env_id, app_id, name, order | (app_id, name) 唯一 |
| ConfigItem | item_id, env_id, key, value, type | (env_id, key) 唯一 |
| ConfigVersion | version_id, env_id, version_no, diff, published_at | version_no 单调递增,发布后不可改 |
| Inheritance | parent_id, child_id, priority | 必须无环,priority 决定覆盖顺序 |
五、领域建模中的两个实践要点
第一,隔离维度必须前置。所有查询接口的第一个参数都应该是 tenant_id,而不是在 SQL 末尾追加过滤条件。领域服务层应提供 TenantContext,由网关解析请求头中的租户标识后注入,业务代码不感知租户切换。这样可以从结构上避免“忘记加租户条件”导致的越权读取。
第二,版本与配置项分离。配置项保存“当前值”,版本保存“历史快照”。发布时先写入新版本记录,再原子更新配置项的当前值指针。回滚时只需把指针指回旧版本,无需反向修改数据。这种设计让审计、回滚和灰度发布都变得简单。
总结来看,多租户配置模型的设计顺序应当是:先确定隔离边界(租户),再确定归属层级(应用、环境),然后定义最小单元(配置项)与不可变快照(版本),最后用继承关系把复用路径串起来。只要这六个对象的归属、唯一约束和解析顺序定义清楚,后续的存储选型、缓存策略和发布流程都会变得有据可依。