租户隔离怎么做MYSQL_基于JPA实现SaaS多租户模式的数据存储——共享数据库,隔离数据架构...
SaaS是Software-as-a-Service(软件即服务)的简称,这边具体的解释不介绍。多租户的系统可以应用这种模式的思想,将思想融入到系统的设计之中。现在SaaS Multi-Tenant在数据存储上存在两大类共三种主要的方案,分别是:独立数据库和共享数据库,其中共享数据库又可分为共享数据库,隔离数据架构和共享数据库,共享数据架构。 具体如下:独立数据库,即一个Tenant一个Datab
SaaS是Software-as-a-Service(软件即服务)的简称,这边具体的解释不介绍。多租户的系统可以应用这种模式的思想,将思想融入到系统的设计之中。
现在SaaS Multi-Tenant在数据存储上存在两大类共三种主要的方案,分别是:独立数据库和共享数据库,其中共享数据库又可分为共享数据库,隔离数据架构和共享数据库,共享数据架构。 具体如下:
独立数据库,即一个Tenant一个Database,这种方案的用户数据隔离级别最高,安全性最好,但成本也高。
共享数据库,隔离数据架构, 即多个或所有租户共享Database,但一个Tenant一个Schema。
共享数据库,共享数据架构, 即租户共享同一个Database、同一个Schema,但在表中通过TenantID区分租户的数据。这是共享程度最高、隔离级别最低的模式。
1.下面简单谈谈基于JPA实现上述的第二种方案:创建数据库demo,表名tb_user,tb_user_1,tb_user_2,tb_user_3。表结构如下图所示:
图1-1 表结构
2.使用经典的三层架构(3-tier application)开发web应用,此时完成了最最最普通的查询与保存功能。如下图所示:
图2-1 application.properties
图2-2 controller
图2-3 service
图2-4 dao
图2-5 model
图2-6 状态枚举
3.通过1和2两个步骤我们已经可以正常的查询和保存数据了,但是全都保存在了tb_user表中,实际上我们多租户系统是需要根据tenantId来将数据保存到不同的表中的。接下来就是重点。创建共享常量类用来保存需要分表的表名集合或数组。我们将表名写到配置文件中split.table.list,方便修改。
图3-1 共享常量
4.创建本地线程共享变量用来存放租户ID,接口请求时就是根据前端传的租户Id来区分是哪一个租户。这里还可以扩展一下,比如接口请求实际上花费了多少时间等等,将有用的字段定义一下。
图4-1 本地线程共享变量
5.实现WebMvcConfigurer接口里的addInterceptors方法添加全局拦截器,在全局拦截器里我们拦截每一个请求,将租户ID存到我们的本地线程共享变量中。
图5-1 WebMvcConfigurer
图5-2 interceptor
6.这一步才是重中之重,划重点。继承EmptyInterceptor类重写onPrepareStatement方法,onPrepareStatement方法是在准备sql字符串时调用的,所以这里我们可以将其稍微改造一下。根据本地线程共享变量中的租户ID和需要分表的表名来修改对应sql语句,最后返回原始或修改过的sql。这样就以为大功告成了吗,错了,还需要再配置一下hibernate拦截器实现的包名路径:spring.jpa.properties.hibernate.ejb.interceptor=com.saas.demo.config.JpaInterceptor
图6-1 hibernate拦截器
经过上面6个步骤,我们已经实现了JPA分表的功能,调用一下接口http://127.0.0.1:10002/user/users查看数据,Http消息头(Http Headers)里添加tenantId值作为租户的区分。看看结果:
租户1结果
租户2结果
租户1(tb_user_1)事先插入了一条数据,租户2(tb_user_2)没有数据。ok,大功告成,收工。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)