多租户
在SaaS数据分析平台上,多个租户(例如组织、客户或业务部门)共享相同的数据库基础设施,同时保持其数据的逻辑分离是很常见的。这使得不同的用户可以在同一平台上安全地访问自己的数据。
根据需求,有不同的方法来实现多租户。以下是如何在ClickHouse Cloud中实现它们的指南。
共享表
在这种方法中,所有租户的数据存储在一个共享表中,使用一个字段(或一组字段)来标识每个租户的数据。为了最大化性能,这个字段应该包含在主键中。为了确保用户只能访问各自租户的数据,我们使用基于角色的访问控制,通过行策略来实现。
我们推荐这种方法,因为这是最简单的管理方式,特别是当所有租户共享相同的数据架构且数据量适中(< TBs)时。
通过将所有租户的数据合并到一个表中,存储效率得到了改善,优化的数据压缩和减少的元数据开销。此外,模式更新得到了简化,因为所有数据都集中管理。
这种方法特别有效,适用于处理大量租户(可能达到数百万)。
然而,如果租户具有不同的数据模式或预计会随着时间的推移而差异,替代的方法可能更合适。
在租户之间的数据量存在显著差距的情况下,较小的租户可能会经历不必要的查询性能影响。请注意,这个问题在很大程度上通过将租户字段包含在主键中得以缓解。
示例
这是一个共享表多租户模型实现的示例。
首先,让我们创建一个共享表,其中包含在主键中的字段tenant_id
。
让我们插入虚假数据。
然后让我们创建两个用户user_1
和user_2
。
我们创建行策略,限制user_1
和user_2
仅访问各自租户的数据。
然后使用一个公共角色对共享表进行GRANT SELECT
权限。
现在您可以以user_1
的身份连接并运行简单的选择。只返回第一个租户的行。
独立表
在这种方法中,每个租户的数据存储在同一数据库中的独立表中,无需特定字段来识别租户。用户访问使用GRANT语句 enforced,确保每个用户只能访问包含其租户数据的表。
当租户具有不同的数据模式时,使用独立表是一个不错的选择。
对于涉及少量具有非常大数据集的租户的场景,如果查询性能至关重要,这种方法可能会优于共享表模型。由于无需过滤其他租户的数据,查询可以更高效。此外,主键可以进一步优化,因为主键中不需要包含额外字段(如租户 ID)。
请注意,此方法对于1000个以上的租户不具备扩展性。请参见使用限制。
示例
这是一个独立表多租户模型实现的示例。
首先,让我们为tenant_1
创建一个事件表,并为tenant_2
创建一个事件表。
让我们插入虚假数据。
然后我们创建两个用户user_1
和user_2
。
然后对相应表授予GRANT SELECT
权限。
现在您可以以user_1
的身份连接并从该用户对应的表中运行简单选择。只返回第一个租户的行。
独立数据库
每个租户的数据存储在同一ClickHouse服务中的独立数据库中。
当每个租户需要大量表和可能的物化视图,并且具有不同的数据架构时,这种方法非常有用。然而,如果租户数量较大,管理起来可能会变得具有挑战性。
该实现与独立表方法相似,但不是在表级别授予权限,而是在数据库级别授予权限。
请注意,此方法对于1000个以上的租户不具备扩展性。请参见使用限制。
示例
这是一个独立数据库多租户模型实现的示例。
首先,我们创建两个数据库,一个用于tenant_1
,一个用于tenant_2
。
让我们插入虚假数据。
然后我们创建两个用户user_1
和user_2
。
然后对相应表授予GRANT SELECT
权限。
现在您可以以user_1
的身份连接并在相应数据库的事件表上运行简单选择。只返回第一个租户的行。
计算-计算分离
上述三种方法还可以通过使用仓库进一步隔离。数据通过公共对象存储共享,但每个租户可以拥有自己的计算服务,借助计算-计算分离使用不同的CPU/内存比率。
用户管理与之前描述的方法类似,因为仓库中的所有服务共享访问控制。
请注意,仓库中子服务的数量有限制。请见仓库限制。
独立云服务
最激进的方法是为每个租户使用不同的ClickHouse服务。
这种不太常见的方法是指在法律、安全或接近性的原因下,租户数据需要存储在不同地区的解决方案。
必须在每个服务上创建一个用户帐户,以便用户可以访问各自租户的数据。
这种方法更难以管理,并且带来每个服务的额外开销,因为它们各自需要自己的基础设施来运行。可以通过ClickHouse Cloud API管理服务,使用官方Terraform提供程序也可以进行编排。
示例
这是一个独立服务多租户模型实现的示例。请注意,示例显示在一个ClickHouse服务上创建表和用户,必须在所有服务上进行复制。
首先,我们创建表events
。
让我们插入虚假数据。
然后我们创建两个用户user_1
。
然后对相应表授予GRANT SELECT
权限。
现在您可以以user_1
的身份在租户1的服务上连接并运行简单选择。只返回第一个租户的行。