2. 医疗租户模型设计
在医疗 SaaS 中,“租户”不是简单的“客户账号”,而是一组共享同一套业务规则、同一份数据隔离边界、同一批身份策略的医疗机构集合。它同时承担三个角色:身份归属的根节点、数据隔离的边界、计费与运维的单元。设计租户模型,本质上是在回答四个问题:租户是什么、租户内部怎么分层、租户之间数据在哪里被切断、租户从签约到注销经历哪些状态。
一、租户定义:从“客户”到“治理单元”
医疗场景的租户通常对应一个独立法人或一个独立运营主体,例如“某某市第一人民医院”“某某连锁体检集团”“某某区域医共体”。判断一个对象能否成为租户,关键看它是否同时满足:拥有独立的用户体系、拥有独立的数据可见范围、拥有独立的配置与计费口径。若某分院与总院共用一套人员目录、共用一套患者主索引,则分院更适合作为组织单元而非独立租户。
租户标识建议采用稳定、不可变的 tenant_id(如 t_100237),并配套 tenant_code(如 HOSP-SZ-001)用于人工识别。租户元数据至少包含:租户类型(医院/体检/药房/医共体)、部署模式(共享库/独立库/独立实例)、数据驻留区域、合规等级、状态、创建时间。这些字段决定了后续隔离策略与生命周期动作。
二、组织层级:租户内的树与跨租户的网
租户内部通常是一棵树:租户 → 院区 → 科室 → 岗位/人员。以某三甲医院为例,租户为“市一院”,下设“本部院区”“东院区”,本部院区下设“心内科”“检验科”,心内科下设“主任医师”“住院医师”等岗位。层级的作用是让权限、数据范围、审批流可以沿树继承与覆盖:科室默认继承院区策略,岗位默认继承科室策略,特殊人员可单独授权。
但医疗 SaaS 往往不止一棵树。医共体、医联体、第三方检验中心会让多个租户之间产生受控的横向关系:A 医院可以调阅 B 医院上传的影像,C 检验中心可以接收 D 医院的检验申请。这类关系不能靠“把两个租户合并”解决,而应通过跨租户授权关系表达,例如 tenant_relation(from_tenant, to_tenant, scope, expire_at),并明确授权范围是“只读某类报告”还是“可写某类申请”。
三、数据隔离边界:三种粒度与选择依据
隔离边界决定了“一个租户的数据在物理和逻辑上被切在哪里”。常见有三种粒度:
- 共享库共享表:所有租户数据在同一张表,靠
tenant_id列过滤。成本最低,适合中小型体检、药房类租户。风险是 SQL 漏写条件即越权,因此必须在数据访问层强制注入租户条件,并配合行级安全策略(RLS)。 - 共享库独立 Schema:每个租户一个 Schema,表结构相同、数据物理分离。适合中大型医院,备份恢复可按租户进行,但连接池与迁移管理复杂度上升。
- 独立数据库/独立实例:适合医共体核心院区或合规要求极高的客户,隔离最强,但运维成本与资源占用最高。
选择依据不是“越强越好”,而是看三个参数:合规等级(是否要求数据物理隔离)、租户规模(大租户可独立,小租户共享)、运维能力(能否承受多实例升级)。实际工程中常采用混合策略:核心三甲医院独立库,基层社区医院共享库共享表,通过 tenant.deploy_mode 字段路由。
tenant_id,且跨租户查询必须经过授权关系校验,不能仅靠“当前登录租户”隐式过滤。四、租户生命周期:状态、动作与数据处置
租户不是“建好就永远不变”。完整生命周期包含:申请中 → 已开通 → 试运行 → 正式运行 → 冻结 → 注销。每个状态对应不同的系统动作与数据处置策略。
以“已开通 → 试运行”为例:系统需要初始化租户管理员账号、导入组织层级模板、分配默认角色与权限集、创建默认数据隔离空间、写入计费试用标记。试运行期通常设置 30 天,期间限制并发用户数与数据导出量,便于验证配置正确性。进入“正式运行”时,计费生效、SLA 开始计算、审计日志转为长期保留。
“冻结”通常由欠费或合规违规触发。冻结不等于删除:用户可登录但只读,或完全禁止登录,但数据保留。冻结期建议 90 天,期间允许补缴恢复。超过冻结期进入“注销”,此时执行数据归档:将租户数据导出为加密归档包,保留法定期限(如病历数据按法规保留),然后清理在线库中的租户数据。注销动作必须记录审计日志,并支持在保留期内按法律要求恢复。
五、落地要点:把模型写进配置与代码
租户模型最终要落到可执行的配置上。建议在租户开通时生成一份租户档案,至少包含以下字段,作为后续隔离、计费、运维的统一依据:
| 字段 | 示例值 | 作用 |
|---|---|---|
| tenant_id | t_100237 | 全局唯一,不可变,所有业务表外键 |
| tenant_code | HOSP-SZ-001 | 人工识别与对接编码 |
| tenant_type | hospital | 决定默认角色模板与合规模板 |
| deploy_mode | shared_schema | 决定数据隔离粒度与路由策略 |
| data_region | cn-south | 数据驻留与合规审计 |
| status | trial | 驱动生命周期动作与权限开关 |
| trial_expire_at | 2025-07-01 | 试运行到期自动提醒或转正 |
在代码层面,租户上下文应作为请求级变量贯穿调用链,例如在网关解析 JWT 中的 tenant_id 后写入 TenantContext,数据访问层统一从上下文取租户条件,禁止业务代码手写 tenant_id 过滤。跨租户授权则通过独立的 tenant_relation 表校验,查询时显式传入 from_tenant 与 to_tenant,避免“默认放行”。
综上,医疗租户模型的核心是:用 tenant_id 定义归属,用组织层级表达院内结构,用隔离粒度控制数据边界,用生命周期管理租户从开通到注销的全过程。四者共同构成医疗 SaaS 多租户治理的地基,后续的身份联邦、权限模型与审计体系都建立在这一模型之上。