1. 医疗SaaS多租户架构总览

医疗信息化正在经历一次结构性迁移:从医院自建机房、单院部署的 HIS/LIS/PACS 系统,转向由厂商统一运营、多机构共享基础设施的 SaaS 模式。驱动力来自三方面。其一是成本与运维,中小型诊所、连锁体检机构、第三方检验中心很难承担独立机房、数据库集群与等保测评的持续投入;其二是协同需求,区域医联体、集团化医院希望跨院区共享患者主索引与检验结果;其三是迭代速度,医保接口、电子处方流转、互联互通标准的更新频率远高于传统项目制交付的节奏。SaaS 化让厂商一次开发、多机构复用,但也把「数据隔离」和「合规」这两个问题推到了架构设计的中心。

多租户的定义与三种隔离模型

多租户(Multi-Tenancy)指同一套应用实例与基础设施,同时服务多个相互独立的客户组织(租户),每个租户只能访问自己的数据与配置。在医疗场景中,一个租户通常是一家医院、一个连锁品牌或一个区域平台,租户内部还有科室、院区、医生等更细的层级。隔离强度决定了架构的复杂度与成本,常见三种模型:

  • 共享数据库 + 共享表(行级隔离):所有租户数据存在同一张表,用 tenant_id 列区分。成本最低、扩展性最好,但任何一条漏写 WHERE tenant_id = ? 的 SQL 都会造成跨租户数据泄露,必须配合行级安全策略(如 PostgreSQL RLS)或 ORM 全局过滤器。
  • 共享数据库 + 独立 Schema:每个租户一个 schema,连接时切换 search_path。隔离性优于行级,备份与迁移可按租户进行,但租户数量上千后 schema 管理、连接池与迁移脚本会变得沉重。
  • 独立数据库(或独立实例):隔离性最强,适合对数据主权有硬性要求的三甲医院或跨境业务,代价是成本随租户线性增长,运维自动化要求高。

实际工程中常采用混合策略:普通诊所走行级隔离,付费等级高或合规要求严的租户单独分配数据库,通过租户元数据表记录每个租户的隔离级别与数据源路由键。

合规要求如何反向约束架构

医疗数据的合规不是事后补文档,而是直接决定表结构、日志、密钥与部署拓扑。三类要求最常出现:

合规框架核心约束对架构的直接影响
HIPAA(美国)PHI 的访问控制、审计日志、传输与静态加密、BAA 协议所有 PHI 字段加密存储;访问日志保留 6 年;与云厂商签署 BAA
GDPR(欧盟)数据主体权利、被遗忘权、数据本地化、处理者协议需支持按患者维度导出与删除;欧盟租户数据不得出境,需分区部署
等保 2.0(中国)三级要求身份鉴别、访问控制、安全审计、数据完整性双因素认证、数据库审计、日志集中留存不少于 6 个月

这些要求落到代码层面,会具体表现为:患者姓名、身份证号、手机号等字段在写入前用 AES-256-GCM 加密,密钥由 KMS 按租户维度托管;每次读取 PHI 都写入审计表,记录 tenant_id、user_id、patient_id、action、occurred_at、source_ip;删除请求不是物理删除,而是标记 deleted_at 并在保留期后由后台任务清理,同时保留审计记录以满足合规追溯。

整体技术栈与课程项目

本课程以一个虚构但结构完整的项目 MediCloud 贯穿始终:它面向连锁诊所与第三方检验机构,提供预约、电子病历、检验报告与计费四类核心能力。技术栈选择如下,均为当前主流且可本地复现的方案:

  • 后端:Java 17 + Spring Boot 3,使用 Spring Security 做认证授权,Hibernate 6 配合 Hibernate Filter 实现租户过滤。
  • 数据库:PostgreSQL 16,行级隔离租户使用 RLS 策略,独立租户使用独立 database。
  • 缓存与消息:Redis 7 做会话与租户配置缓存,RabbitMQ 处理报告生成与审计日志异步落库。
  • 前端:React 18 + TypeScript,登录后由后端下发租户上下文,前端所有请求携带 X-Tenant-Id。
  • 基础设施:Docker Compose 本地编排,Kubernetes 生产部署,密钥由 Vault 或云 KMS 管理。

下图给出 MediCloud 的整体分层与租户请求的流转路径,重点标出「租户识别 → 上下文注入 → 数据隔离 → 审计落库」这条贯穿全栈的主线,后续章节会逐层展开其中的每个环节。

MediCloud 多租户请求流转与隔离主线 诊所A / 诊所B / 检验中心 携带 X-Tenant-Id 的请求 API 网关 认证 · 租户识别 · 限流 TenantContext ThreadLocal 注入租户ID 业务服务层(预约 / 病历 / 报告 / 计费) Hibernate Filter 自动追加 tenant_id 条件 共享库 · 行级隔离 PostgreSQL RLS tenant_id 列 + 策略 独立 Schema search_path 切换 中型连锁租户 独立数据库 三甲 / 跨境租户 数据主权要求 审计日志(异步落库 · 保留 ≥ 6 个月) tenant_id · user_id · patient_id · action · ip · time 图例:实线=请求路径 虚线=审计写入