我正在研究SaaS产品并试图找出为我的场景设计数据库的最佳方法,我认为这是非常标准的。
我不应该没有设计这样一个数据库的经验。
我累了在网上研究,但实际上没有任何关于实施的信息。有不少比较不同的多租户架构。
对于多租户方法,我决定使用单个数据库 - 似乎是最合适的。
以下是应该支持的基本列表:
多个客户端,全部分开,不在它们之间共享数据。
每个客户都有自己的用户群(员工/员工)。
客户的工作人员对系统具有不同的访问级别(暴露于不同区域,执行某些操作的能力)
每个客户都拥有自己的客户。
我可以围绕任何表上的tenant_id属于该租户的基本概念。我想我的问题更多的是如何将它与每个客户的员工的不同访问级别相结合。
你会怎么做?
有没有参考过这样一个DB的实现?
谢谢
更新
在@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查找的改进可以是在登录时将访问列表存储在会话上,以消除双连接(获取所有用户的角色,获取所有角色的访问列表)。
问题
首先,您对设计的总体看法是什么?你看到任何缺陷吗?
在session上保存account_id真的需要/一个好主意吗?
让服务器检查用户是否有权访问某个资源是这样做的标准方法吗?有没有办法将此作为自身查询的一部分(例如从数据库本身获取错误)?
同一个表中的多个租户是最糟糕的选择。 你为什么默认它?
更容易维护单个数据库,更好地扩展,更具成本效益...您对它的投票是什么?
有理由不这样做:一些行业法规可能要求更严格的数据隔离,升级/迁移会影响所有租户,无论如何,并且很难使用单个租户数据集。 我在2017年谈到了管理这种技术的技术。
我知道了。 这就是为什么我不认为不同的方法更好或更差。 更适合你想要实现的目标。 在我的情况下,我没有任何这些规则或需求,所以单个DB看起来最合适。
@yohairosen近两年后,您对数据库结构满意吗? 你还用吗? 你会改变回头看吗?
在概述解决方案之前,您可以通过描述要求获得更好的答案。
您的设计似乎描述了授权方案。它看起来相当可靠 - 我用自然语言概括为:
租户是一个帐户。
一个帐户有很多用户。
用户可以拥有
很多角色。
角色授予对许多权限的访问权限。
系统
维护会话列表,将请求映射到用户;这反过来
允许系统检查用户是否具有a的权限
给予行动。
在不了解您的要求的情况下,这似乎相当合理您可能希望包含从"帐户"到应用程序识别为"租户"的链接。
最大的问题是如何在应用程序中使用这些数据。为每个请求检查权限 - 特别是细粒度的权限 - 可能很昂贵。
这里的具体解决方案在很大程度上取决于您的应用程序框架 - 许多都具有内置的身份验证/授权模型,并且使用这些内置功能通常是个好主意。
有关如何实现这一点的想法,您可以查看CanCanCan,一个Ruby on Rails的授权框架,或者Laravel的授权。
还不清楚系统中的实际数据如何链接到帐户 - 如果您的系统跟踪小部件,"小部件"表是否有"account_id"列?如果是这样,您的应用程序如何跟踪谁是和不允许访问该行?
我同意,你的清单总结得很好。 拥有租户和帐户会带来什么好处? 你问的(大)问题正是我想得到的一些意见 - 我认为它可能也很昂贵 - 是否还有另一种方法呢? 我在问题中建议的"改进"怎么样? 缓存会话中的权限列表? ...是的,所有相关的"对象"/"行"都有一个account_id-举个例子,我将检查用户的角色是否具有与其关联的"小部件"的"访问"。思考?
我已经更新了答案 - 对于您正在使用的应用程序框架而言,这确实是一个问题,而不是数据库设计。 但是,一般而言,我认为超级细化权限可能过度 - 您可以通过对应用程序需要支持的角色进行建模来获得更清晰的设计。
听起来你正在将数据库用户与应用程序用户混为一谈。在具有共享模式模型的SaaS产品中,单个用户不会直接访问数据库;相反,您的应用程序作为单个用户连接,并对所需的所有对象具有适当的权限。您担心的是应用程序用户可以访问的区域以及可以采取的操作。这意味着您需要在模式中构建授权模型。
最简单的模型有两种访问级别:常规用户和管理员。这可以用users表来表示,该表具有tenant_id以将各个登录与正确的客户端相关联,以及is_admin标志。然后,您的应用程序确保只有具有该标志集的用户才能访问管理功能。如果您的授权模型更复杂,请相应地设计您的模式(例如,users可能与roles有很多:很多关系)。
另请注意,对于与tenants直接相关的表,仅严格要求tenant_id列;如果您的profiles表具有user_id,则可以通过users将关系追溯到租户。在某些情况下,添加tenant_id以避免长连接链可能是有意义的。
谢谢你让我朝着正确的方向前进。 更新了我的问题。