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