我正在开发一个需要支持数千名用户的未来多租户Web应用程序。该应用程序正在基于Java的Play上构建!使用JPA / Hibernate和postgreSQL的MVC框架。
我看过Guy Naor关于 Writing Multi-tenant Applications in Rails的谈话,其中谈到了多租户的几种方法(数据隔离随着你的名单而减少):
我选择了方法#2,其中某种用户ID从请求中解析出来,然后用于访问该用户表空间。在进行任何查询之前,会给出postgres SET search_path TO customer_schema,public
命令,以确保客户的表是查询的目标。这可以通过 Play!中的控制器方法中的@Before
控制器注释轻松完成(这是他在rails示例中使用的方法)。 postgres中的 search_path 与操作系统中$PATH
的行为完全相同;真棒!
所有这些听起来都很棒,但我在JDBC / Hibernate / JPA堆栈上实现它时遇到了困难,因为似乎没有办法在运行时动态切换模式。
似乎数据库连接是由连接工厂静态配置的(请参阅:How to manage many schemas on one database using hibernate)。我发现类似的问题与每个用户使用多个SessionFactorys的类似答案,但因为我理解SessionFactorys是重量级的对象,所以你可以支持数百个用户,更不用说成千上万的用户,走这条路线是不可信的。
我还没有完全认真对待上面的#2,但我还没有完全抛弃#3方法。
答案 0 :(得分:5)
您可以执行命令
SET search_path TO customer_schema,public
在同一个连接/会话/事务中,根据需要经常使用。它只是另一个命令,如SELECT 1;
。更多内容见manual here。
当然,您也可以为每位用户预设search_path
。
ALTER ROLE foo SET search_path=foo, public;
如果每个用户或其中许多用户拥有与其用户名匹配的架构,您只需使用default setting in postgresql.conf:
search_path="$user",public;
此处设置search_path
的更多方法:
How does the search_path influence identifier resolution and the "current schema"
答案 1 :(得分:1)
从Hibernate 4.0开始,歧视器(customerID),架构和数据库级别本身支持多租户。请参阅源代码here和单元测试here。
难点在于,虽然单元测试的文件名是SchemaBasedMultitenancyTest,但实际使用的MultitenancyStrategy是Database。我找不到任何关于如何使其基于模式工作的示例,但也许单元测试将足以继续......
答案 2 :(得分:1)
虽然按模式进行分片很常见,但请参阅Apartment gem作者的this post,其中包含一些缺点。
在Citus,我们通过上面列出的选项#3进行分片,您可以在文档中的use-case guide中阅读更多内容。