【问题标题】:Designing a SaaS on a single database, multi-tenant (SQL)在单个数据库、多租户 (SQL) 上设计 SaaS
【发布时间】:2018-07-02 16:47:02
【问题描述】:

我正在开发一个 SaaS 产品,并试图找出为我的场景设计数据库的最佳方法,我认为这是非常标准的。

我不应该说我没有设计这样一个数据库的经验。

我厌倦了在线研究,但我找不到任何关于实施的信息。有很多比较不同的多租户架构。

对于多租户方法,我决定使用单个数据库 - 这似乎是最合适的。

以下是应支持的基本列表:

  • 多个客户端,全部分离,它们之间不共享数据。
  • 每个客户都有自己的用户群(员工/员工)。
  • 客户的工作人员对系统有不同的访问级别(接触不同的区域、执行某些操作的能力)
  • 每个客户都有自己的客户。

我可以理解以下基本概念:任何桌子上的tenant_id 都属于该租户。我想我的问题更多在于如何将它与每个客户员工的不同访问级别结合起来。

你会怎么做? 有没有参考这种数据库的一些实现?

谢谢


更新

@dmfy 回答后,我想了想,想出了这个解决方案:

account
 -id
 -name

user
 -id
 -account_id
 -username
 -password

role
 -id
 -account_id
 -name

user_role
 -user_id
 -role_id

access
 -id
 -role_id
 -name

role_access
 -role_id
 -access_id

session
 -account_id
 -user_id
 -token

我会解释-

role 表本质上是与权限/访问级别列表相关联的用户“组”。

access 表表示单个权限。平台的一个区域,可以(或不能)执行的操作。

成功登录后会在session 表中创建一行。每次调用服务器时,如果用户已通过令牌验证,我将查找该用户的角色(使用 user_roles 上的 session.user_id 并使用 role.id 收集它的 access 列表role_access.role_id)。

获得访问列表后,我可以检查请求并查看是否允许用户执行操作。

  • 注意事项
    • role 可以为每个租户/帐户定制(例如,一个可以有“管理”和“员工”,另一个可以有“管理”、“支持”和“销售”),因此与 account 的关联。
    • 另一方面,access 是平台范围的。该平台在所有租户中具有相同的区域和操作集。因此无需将其与特定帐户关联。
    • access 查找的改进可能是在登录时将访问列表存储在会话中,以消除双重连接(获取所有用户的角色,获取所有角色的访问列表)。

问题

  • 首先,您对设计的总体看法是什么。您发现任何缺陷吗?
  • account_id 保存在session 上真的需要/一个好主意吗?
  • 服务器检查用户是否有权访问某个资源是执行此操作的标准方法吗?有没有办法将其作为自身查询的一部分(例如从数据库本身获取错误)?

【问题讨论】:

  • 多个租户在同一个表是最糟糕的选择。你为什么默认它?
  • 更容易维护单个数据库,更好地扩展,更具成本效益......你的反对票是什么?
  • 有理由不这样做:一些行业法规可能要求更严格的数据隔离,升级/迁移无论如何都会影响所有租户,并且很难处理单个租户数据集。我给了talk 一个关于 2017 年最后一次管理的技术。
  • 我明白了。这就是为什么我不认为不同的方法更好或更坏。更适合您想要实现的目标。就我而言,我没有任何这些规定或需求,因此单个数据库看起来最合适。
  • @yohairosen 将近 2 年之后,您对数据库结构感到满意吗?你还在用吗?回顾过去,你会改变什么吗?

标签: mysql sql database-design roles saas


【解决方案1】:

听起来您将 database 用户与 application 用户混为一谈。在具有共享模式模型的 SaaS 产品中,个人用户将无法直接访问数据库;相反,您的应用程序以对它需要的所有对象具有适当权限的单个用户身份连接。您担心的是应用程序用户可以访问哪些区域以及他们可以采取哪些操作。这意味着您需要将授权模型构建到您的架构中。

最简单的模型有两个访问级别:普通用户和管理员。这可以用一个users 表来表示,该表具有一个tenant_id 以将个人登录与正确的客户端相关联,以及一个is_admin 标志。然后,您的应用程序确保只有设置了标志的用户才能访问管理功能。如果您的授权模型更复杂,请适当地设计您的架构(例如,users 可能与 roles 具有多对多关系)。

另请注意,tenant_id 列仅对与tenants 直接相关的表是严格要求的;如果您有一个带有user_idprofiles 表,则可以通过users 将关系追溯到租户。在某些情况下,添加tenant_id 以避免长连接链可能是有意义的。

【讨论】:

  • 感谢您向正确的方向发送我的信息。更新了我的问题。
【解决方案2】:

在概述解决方案之前,通过描述需求可能会得到更好的答案。

您的设计似乎描述了一种授权方案。它看起来相当可信 - 我会用自然语言将其总结为:

  • 租户是一个帐户。
  • 一个帐户有很多用户。
  • 用户可以拥有 很多角色。
  • 角色授予对许多权限的访问权限。
  • 系统 维护会话列表,将请求映射到用户;这反过来 允许系统检查用户是否有权限 给定的行动。

在不知道您的要求的情况下,这似乎是相当合理的。您可能希望包含一个从“帐户”到您的应用程序识别为“租户”的链接。

最大的问题是您将如何在应用程序中使用这些数据。检查每个请求的权限——尤其是细粒度的权限——可能会很昂贵。

这里的具体解决方案在很大程度上取决于您的应用程序框架 - 许多都有内置的身份验证/授权模型,使用这些内置功能通常是个好主意。

有关如何实现此功能的想法,您可以查看CanCanCan,这是一个用于 Ruby on Rails 的授权框架,或Authority 用于 Laravel。

也不清楚您系统中的实际数据将如何链接到一个帐户 - 如果您的系统跟踪小部件,“小部件”表是否有一个“account_id”列?如果是这样,您的应用程序如何跟踪允许和不允许访问该行的人?

【讨论】:

  • 我同意,你的清单总结得很好。拥有租户和帐户有什么好处?你问的(大)问题正是我想得到一些意见的——我认为它可能也很昂贵——还有其他方法吗?我在我的问题中建议的“改进”呢?缓存会话中的权限列表? ...是的,所有相关的“对象”/“行”都会有一个 account_id - 以你的例子为例,我将检查用户的角色是否具有与之关联的“小部件”的“访问权限”。想法?
  • 我已经更新了答案——这确实是您正在使用的应用程序框架的问题,而不是数据库设计的问题。不过,总的来说,我认为超细化权限可能有点过头了——您可以通过对应用程序需要支持的角色进行建模来获得更简洁的设计。
猜你喜欢
  • 2012-09-24
  • 2022-01-11
  • 2016-10-19
  • 2021-07-10
  • 2018-01-31
  • 2014-07-15
  • 1970-01-01
  • 2019-10-02
  • 1970-01-01
相关资源
最近更新 更多