SaaS 多租户数据隔离(二):摒弃字段过滤,实战基于 Schema 的物理隔离终极形态

满足极其挑剔的高端医疗机构安全诉求。极其决绝地实施Database级物理切割,配合ThreadLocal极度精妙的动态数据源路由与Flyway的极其狂暴的基建自动化。

在上一篇探讨 SaaS 多租户(Multi-Tenant)架构的文章中,我们极其硬核地剖析了基于 Mybatis-Plus 拦截器的“共享表,字段隔离(Tenant_ID)”方案。
不可否认,那是极其轻量、极其省钱的极客解法。
但在橙星云极其深度的商业化进程中,我们迎来了极其挑剔的省级教育巨头和极其严苛的医疗集团。

他们对数据的极其变态的隐私要求是:“我们的学生极其机密的档案,绝对不允许和别的野鸡机构极其肮脏地混在同一张 MySQL 表里!万一你们代码极其脑残地漏写了一个 Tenant_ID 条件,数据串库的后果是极其惨烈的物理灾难!

面对这种极度苛刻的安全诉求,架构师必须极其果断地抛弃字段级别的极其脆弱的逻辑防御,转身祭出极其强悍、极其暴力的终极防线:基于 Schema(库级)的绝对物理隔离。本文将硬核拆解这套极具破坏力的高端架构。

极其决绝的物理切割:Schema 隔离的极客哲学

在 Schema 隔离的极其暴力的世界里。
如果有 100 个极其尊贵的付费机构。我们在同一个 MySQL 实例中,不是极其愚蠢地建一张极其庞大的表,而是极其冷酷地直接 CREATE DATABASE 创建 100 个极其孤立的数据库实例(Schema)!
机构 A 的数据极其安稳地躺在 psydbtenanta 里;机构 B 的极其机密的数据绝对死锁在 psydbtenantb 里。

这就像给每个机构极其阔绰地发了一把绝对独一无二的极其沉重的铜锁。哪怕业务代码再极其弱智地写了一句极其恐怖的 SELECT * FROM student 忘了加过滤条件,它也绝对极其不可能查到其他库的数据,因为物理墙壁已经将其极其无情地彻底封死!

极度烧脑的动态数据源(Dynamic DataSource)路由

物理隔离极其爽,但代码怎么写?难道要极其愚蠢地配置 100 个 JDBC 连接池吗?
极客的解法是极其玄妙的动态数据源路由(Dynamic Routing DataSource)

在 Spring Boot 中,我们极其巧妙地利用极其核心的 ThreadLocal 编织一张极度隐蔽的路由网。

  1. 极其敏锐的前置侦测:当机构 A 的管理员发来一个 HTTP 请求时,极客网关极其迅速地从极其机密的 JWT Token 中剥离出该机构的租户标识(Tenant = A)。
  2. 极其隐蔽的线程绑定:拦截器极其迅速地将这个标识塞进极其私密的 ThreadLocal 变量中,让这个极其隐蔽的记号极其安静地伴随整个请求线程的生命周期。
  3. 极其狂暴的底层劫持:当 MyBatis 执行到极其底层的数据库连接阶段时。我们极其霸道地重写了 Spring 的 AbstractRoutingDataSourcedetermineCurrentLookupKey() 方法。

它会极其聪明地去 ThreadLocal 里摸一把,极其精准地拿到“A”。然后,数据源连接池会极其丝滑地瞬间切换,将这条 SQL 极其致命地砸向 psydbtenant_a 这个数据库!

极其恐怖的运维黑洞与极客基建(Flyway)

别高兴得太早!Schema 隔离最大的极其致命的报应在于极度恐怖的数据库版本运维
当你极其兴奋地要发版一个新功能,需要在 student 表里加一个极其普通的 age 字段时。
在以前,你只需要极其轻松地执行 1 次极其简单的 SQL。而现在,你面对的是 100 个极其分散的数据库,你需要极其痛苦地去执行 100 次!

为了填平这个极其可怕的黑洞,架构组极其果断地引入了极其强悍的自动化数据库迁移工具:Flyway
在应用启动的那极其关键的几秒钟里,启动脚本会极其疯狂地遍历那 100 个租户库,利用 Flyway 极其严厉的版本控制,极其自动、极其无情地将最新的极其关键的 DDL(表结构变更)极其精准地刷入每一个极其孤立的库中。彻底抹杀了极其危险的人工干预。

总结

在 B 端 SaaS 的极其残酷的数据隐私战场上,高端客户的信任往往建立在极度硬核的物理防御之上。
通过极其果断地实施 Schema 级别的极度冷酷的物理隔离,辅以 ThreadLocal 极度精妙的动态路由与 Flyway 极度狂暴的基建自动化。极客架构师在付出极大的运维代价的同时,极其霸气地斩断了任何极其微小的数据串库风险,为省级巨头献上了一座极度坚不可摧的数据孤岛城堡。

Leave a Reply

Your email address will not be published. Required fields are marked *