我们有一个SaaS应用程序,每个租户在Postgres都有自己的数据库。如何将补丁应用于所有数据库?例如,如果我想添加一个表或向表添加一个列,我必须编写一个循环遍历所有数据库并对其执行SQL或使用pgadmin的程序,逐个查看它们。
是否有更聪明和/或更快的方式?
非常感谢任何帮助。
答案 0 :(得分:4)
是的,这是一种更聪明的方式。
不要为每个租户创建新数据库。如果所有内容都在一个数据库中,那么您只需要更改一个数据库。
选择一个数据库,更改每个表以使列TENANT并将其添加到主键。然后将所有租户的每条记录插入此数据库并删除其他数据库(显然需要更多工作,因为您的应用程序需要更改)。
在其他地方广泛讨论了与您的方法的差异:
如果你没有将所有内容放在一个数据库中,那么我担心你必须单独更改它们,并且以编程方式进行更简单。
答案 1 :(得分:2)
在更高级别,所有多租户应用程序都遵循以下三种方法之一:
我经常发现开发人员在评估这些不同的方法时会使用以下标准。
隔离:由于您可以一方面将每个租户放入自己的数据库,并让租户在另一方面共享同一个表,因此这将成为最明显的维度。如果您为用户提供原始SQL访问权限,或者您处于受监管的行业(例如医疗保健),则可能需要从数据库中获得严格的保证。也就是说,PostgreSQL 9.5附带了行级安全策略,这使得大多数应用程序都不会担心这个问题。
可扩展性:如果您的租户共享相同的架构(方法#3),并且您的租户的字段不同,那么您需要考虑如何合并这些字段。
关于multi-tenant databases的这篇文章对不同的方法有很好的总结。例如,您可以添加十几列,将它们称为C1,C2等,然后让您的应用程序根据tenant_id推断此列中的实际数据。 PostgresQL 9.4附带JSONB支持,本机允许您使用半结构化字段来表示不同租户数据之间的差异。
缩放:另一个标准是数据库扩展的容易程度。如果您为每个数据库或模式(上面的#1或#2)创建租户,您的应用程序可以使用现有的Ruby Gems或[Django软件包] [1]来简化应用程序集成。也就是说,您需要手动管理租户的数据和他们所居住的机器。类似地,您需要构建自己的分片逻辑来传播外键约束和ALTER TABLE命令。
使用方法#3,您可以使用现有的开源扩展解决方案,例如Citus。例如,this blog post描述了如何使用Postgres轻松地对多租户应用进行分片。
答案 2 :(得分:1)
现在是时候回馈社区了:)所以4年后,我们的多租户平台正在制作中,我想与大家分享以下观察/经验。
我们为每个租户使用了一个数据库。这为我们提供了极大的灵活性,因为备份中的数据库大小并不大,因此我们可以轻松地将它们导入到我们的暂存环境中以解决客户问题。
我们使用Liquibase进行数据库开发和升级。这对我们来说是一个巨大的帮助,允许我们将整个构建打包成一个简单的war文件。所有更改都可以轻松地进行版本控制和管理。这里有一点学习曲线,但没有什么实质性的。 2-5天可以大大节省您的时间。
鉴于我们使用Spring / JPA / Hibernate,我们使用一种称为动态数据源路由的技术。因此,当用户登录时,我们会通过查找找到相关的数据源,并将它们连接到正确数据库的会话。这也是Liquibase脚本应用于更新的时候。
现在,我将在稍后再回来。
答案 3 :(得分:0)
当然,对于我们来说,所有租户的一个数据库肯定存在问题。
备份文件越来越大,几乎变得难以管理
为进行故障排除,我们需要在开发环境中还原客户的数据,我们只使用该客户的备份文件,通常该文件的大小不像我们要为所有客户使用一个数据库那样大。
同样,Liquibase对于允许无缝管理所有租户的更新而没有任何问题是至关重要的。没有Liquibase,我会看到这种方法的许多复杂性。因此,Liquibase,Liquibase和更多Liquibase。
我还怀疑我们需要一个更强大的硬件来管理一个庞大的数据库,该数据库具有跨数百万条记录的大型联接,而管理轻量级的数据库却具有较小的查询量。
在出现问题的情况下,该服务并不能为所有人服务,并且只能容纳一个或几个租户。
总的来说,对于我们而言,这是一个伟大的架构决策,我们每天都在从中受益。有一次,我们有一位没有激活归档功能的客户,他们的数据库大小增长到3 GB以上。随着离岸团队的发展,互联网速度的下降以及存储/带宽的价格下降,人们很快就会发现事情如何变得复杂。
希望这对某人有帮助。
-雷克斯