对Rails中的多租户与多数据库应用程序的任何想法

时间:2023-01-29 16:58:09

Our app currently spawns a new database for each client. We're starting to wonder whether we should consider refactoring this to a multi-tenant system.

我们的应用程序当前为每个客户端生成一个新数据库。我们开始怀疑是否应该考虑将其重构为多租户系统。

What benefits / trade-offs should we be considering? What are the best practices for implementing a multi-tenant app in Rails?

我们应该考虑哪些利益/权衡?在Rails中实现多租户应用程序的最佳实践是什么?

5 个解决方案

#1


8  

I've been researching the same thing and just found this presentation to offer an interesting solution: Using Postgre's schemas (a bit like namespaces) to separate data at the DB level while keeping all tenants in the same DB and staying (mostly) transparent to rails.

我一直在研究同样的事情,只是发现这个演示文稿提供了一个有趣的解决方案:使用Postgre的模式(有点像名称空间)来分离数据库级别的数据,同时保持所有租户在同一个数据库中并保持(大部分)透明轨道。

Writing Multi-Tenant Applications in Rails - Guy Naor

在Rails中编写多租户应用程序 - Guy Naor

#2


6  

Multi-tenant systems will introduce a whole range of issues for you. My quick thoughts are below

多租户系统将为您介绍一系列问题。我的快速想法如下

  • All SQL must be examined and refactored to include a ClientId value.

    必须检查和重构所有SQL以包含ClientId值。

  • All Indexes must be examined to determine if the ClientId needs to be included

    必须检查所有索引以确定是否需要包含ClientId

  • An error in a SQL statement by a developer/sysadmin in production will affect all of your customers.

    生产中的开发人员/系统管理员在SQL语句中的错误将影响您的所有客户。

  • A database corruption/problem will affect all of your customers

    数据库损坏/问题将影响您的所有客户

  • You have some data privacy issues whereby poor code/implementation could allow customerA to see data belonging to CustomerB

    您有一些数据隐私问题,因此糟糕的代码/实现可能允许customerA查看属于CustomerB的数据

  • A customer using your system in a heavy/agressive manner may affect other customers perception of performance

    以沉重/激进的方式使用您的系统的客户可能会影响其他客户对性能的感知

  • Tailoring static data to an individual customers preference becomes more complex.

    根据个人客户偏好调整静态数据变得更加复杂。

I'm sure there are a number of other issues but these were my initial thoughts.

我确定还有其他一些问题,但这些是我最初的想法。

#3


2  

It really depends upon what you're doing.

这取决于你在做什么。

We are making a MIS program for the print industry that tracks inventory, employees, customers, equipment, and does some serious calculations to estimate costs of performing jobs based on a lot of input variables.

我们正在为印刷行业制作MIS程序,跟踪库存,员工,客户,设备,并进行一些严肃的计算,以估算基于大量输入变量执行作业的成本。

We are anticipating very large databases for each customer, and we currently have 170 tables. Adding another column to almost every table just to store the client_id hurts my brain.

我们期待为每个客户提供非常大的数据库,目前我们有170个表。为了存储client_id,几乎每个表都添加另一列会伤害我的大脑。

We are currently in the beta stage of our program, and here are some things that we have encountered:

我们目前处于我们计划的测试阶段,以下是我们遇到的一些问题:

  • Migrations: A Rails assumption is that you will only have 1 database. You can adapt it for multiple databases, and migrations is one of them. You need a custom rake task to apply migrations to all existing databases. Be prepared to do a lot of trouble shooting because a migration may succeed on one DB, but fail on another.
  • 迁移:Rails假设您只有1个数据库。您可以针对多个数据库进行调整,迁移就是其中之一。您需要自定义rake任务才能将迁移应用于所有现有数据库。准备好做很多麻烦,因为迁移可能在一个数据库上成功,但在另一个数据库上失败。
  • Spawning Databases: How do you create a new db? From a SQL file, copying an existing db, or running all migrations? How do you keep you schema consistent between your table creation system, and your live databases?
  • 产卵数据库:如何创建新的数据库?从SQL文件复制现有数据库,还是运行所有迁移?如何在表创建系统和实时数据库之间保持模式一致?
  • Connecting to the appropriate database: We use a cookie to store a unique value that maps to the correct DB. We use a before filter in an Authorized controller that inheirits from ActionController that gets the db from that unique value and uses the establish_connection method on a Subclass of ActiveRecord::Base. This allows us to have some models pull from a common db and others from the client's specific db.
  • 连接到适当的数据库:我们使用cookie来存储映射到正确数据库的唯一值。我们在Authorized控制器中使用before过滤器,该控制器从ActionController获取,从该唯一值获取db并在ActiveRecord :: Base的子类上使用establish_connection方法。这允许我们从公共数据库中获取一些模型,从客户端的特定数据库中获取其他模型。

If you have specific questions about any of these, I can help.

如果您对这些问题有任何疑问,我可以提供帮助。

#4


0  

I don't have any experience with this personally, but during the lightning talks at the 2009 Ruby Hoedown, Andrew Coleman presented a plugin he designed and uses for multi-tenant databases in rails w/ subdomains. You can check out the lightning talk slides and here's the acts_as_restricted_subdomain repository.

我个人没有任何经验,但在2009年Ruby Hoedown的闪电谈话中,Andrew Coleman提出了一个他设计的插件,用于带有子域的rails中的多租户数据库。您可以查看闪电谈话幻灯片,这里是acts_as_restricted_subdomain存储库。

#5


0  

Why would you? Do you have heavy aggregation between users or are you spawning too many DBs? Have you considered using SQLite files per tenant instead of shared DB servers (since multitenant apps often are low-profile and don't need that much concurrency)?

你为什么这样?您是否在用户之间进行了大量聚合,或者您是否产生了太多的数据库?您是否考虑过每个租户使用SQLite文件而不是共享数据库服务器(因为多租户应用程序通常都是低调的,并且不需要那么多并发)?

#1


8  

I've been researching the same thing and just found this presentation to offer an interesting solution: Using Postgre's schemas (a bit like namespaces) to separate data at the DB level while keeping all tenants in the same DB and staying (mostly) transparent to rails.

我一直在研究同样的事情,只是发现这个演示文稿提供了一个有趣的解决方案:使用Postgre的模式(有点像名称空间)来分离数据库级别的数据,同时保持所有租户在同一个数据库中并保持(大部分)透明轨道。

Writing Multi-Tenant Applications in Rails - Guy Naor

在Rails中编写多租户应用程序 - Guy Naor

#2


6  

Multi-tenant systems will introduce a whole range of issues for you. My quick thoughts are below

多租户系统将为您介绍一系列问题。我的快速想法如下

  • All SQL must be examined and refactored to include a ClientId value.

    必须检查和重构所有SQL以包含ClientId值。

  • All Indexes must be examined to determine if the ClientId needs to be included

    必须检查所有索引以确定是否需要包含ClientId

  • An error in a SQL statement by a developer/sysadmin in production will affect all of your customers.

    生产中的开发人员/系统管理员在SQL语句中的错误将影响您的所有客户。

  • A database corruption/problem will affect all of your customers

    数据库损坏/问题将影响您的所有客户

  • You have some data privacy issues whereby poor code/implementation could allow customerA to see data belonging to CustomerB

    您有一些数据隐私问题,因此糟糕的代码/实现可能允许customerA查看属于CustomerB的数据

  • A customer using your system in a heavy/agressive manner may affect other customers perception of performance

    以沉重/激进的方式使用您的系统的客户可能会影响其他客户对性能的感知

  • Tailoring static data to an individual customers preference becomes more complex.

    根据个人客户偏好调整静态数据变得更加复杂。

I'm sure there are a number of other issues but these were my initial thoughts.

我确定还有其他一些问题,但这些是我最初的想法。

#3


2  

It really depends upon what you're doing.

这取决于你在做什么。

We are making a MIS program for the print industry that tracks inventory, employees, customers, equipment, and does some serious calculations to estimate costs of performing jobs based on a lot of input variables.

我们正在为印刷行业制作MIS程序,跟踪库存,员工,客户,设备,并进行一些严肃的计算,以估算基于大量输入变量执行作业的成本。

We are anticipating very large databases for each customer, and we currently have 170 tables. Adding another column to almost every table just to store the client_id hurts my brain.

我们期待为每个客户提供非常大的数据库,目前我们有170个表。为了存储client_id,几乎每个表都添加另一列会伤害我的大脑。

We are currently in the beta stage of our program, and here are some things that we have encountered:

我们目前处于我们计划的测试阶段,以下是我们遇到的一些问题:

  • Migrations: A Rails assumption is that you will only have 1 database. You can adapt it for multiple databases, and migrations is one of them. You need a custom rake task to apply migrations to all existing databases. Be prepared to do a lot of trouble shooting because a migration may succeed on one DB, but fail on another.
  • 迁移:Rails假设您只有1个数据库。您可以针对多个数据库进行调整,迁移就是其中之一。您需要自定义rake任务才能将迁移应用于所有现有数据库。准备好做很多麻烦,因为迁移可能在一个数据库上成功,但在另一个数据库上失败。
  • Spawning Databases: How do you create a new db? From a SQL file, copying an existing db, or running all migrations? How do you keep you schema consistent between your table creation system, and your live databases?
  • 产卵数据库:如何创建新的数据库?从SQL文件复制现有数据库,还是运行所有迁移?如何在表创建系统和实时数据库之间保持模式一致?
  • Connecting to the appropriate database: We use a cookie to store a unique value that maps to the correct DB. We use a before filter in an Authorized controller that inheirits from ActionController that gets the db from that unique value and uses the establish_connection method on a Subclass of ActiveRecord::Base. This allows us to have some models pull from a common db and others from the client's specific db.
  • 连接到适当的数据库:我们使用cookie来存储映射到正确数据库的唯一值。我们在Authorized控制器中使用before过滤器,该控制器从ActionController获取,从该唯一值获取db并在ActiveRecord :: Base的子类上使用establish_connection方法。这允许我们从公共数据库中获取一些模型,从客户端的特定数据库中获取其他模型。

If you have specific questions about any of these, I can help.

如果您对这些问题有任何疑问,我可以提供帮助。

#4


0  

I don't have any experience with this personally, but during the lightning talks at the 2009 Ruby Hoedown, Andrew Coleman presented a plugin he designed and uses for multi-tenant databases in rails w/ subdomains. You can check out the lightning talk slides and here's the acts_as_restricted_subdomain repository.

我个人没有任何经验,但在2009年Ruby Hoedown的闪电谈话中,Andrew Coleman提出了一个他设计的插件,用于带有子域的rails中的多租户数据库。您可以查看闪电谈话幻灯片,这里是acts_as_restricted_subdomain存储库。

#5


0  

Why would you? Do you have heavy aggregation between users or are you spawning too many DBs? Have you considered using SQLite files per tenant instead of shared DB servers (since multitenant apps often are low-profile and don't need that much concurrency)?

你为什么这样?您是否在用户之间进行了大量聚合,或者您是否产生了太多的数据库?您是否考虑过每个租户使用SQLite文件而不是共享数据库服务器(因为多租户应用程序通常都是低调的,并且不需要那么多并发)?