设计 SaaS 数据库架构
第一周做出的错误数据库决策会在未来几年一直困扰你。
SaaS 创始人需要一个能够处理多租户、计费和增长的模式(schema)。如果你做错了,半年后你就得重写整个系统。
以下是构建生产级模式的方法。
1. 选择你的租户策略
你必须隔离不同客户之间的数据。
• 行级(共享数据库):复杂度低。最适合大多数初创公司。在每个查询中使用 WHERE organization_id = ? 过滤器。
• Schema 级(独立 Schema):复杂度中等。适用于合规性需求。
• 数据库级(独立数据库):复杂度高。最适合企业级客户。
对于 90% 的新产品来说,行级多租户是正确的选择。
2. 正确的实体层级结构
不要直接向用户计费。用户会流失,但组织会留存。
层级结构应该如下所示: User ── MemberOf ── Organization ── Subscription ── Invoice
• Users:仅将此表用于身份识别。使用 UUID 以防止攻击。 • Organizations:这是你的租户边界。务必将订阅(subscriptions)与组织关联。 • Memberships:使用关联表(join table)将用户与组织连接起来。将角色(roles)存储在这里,而不是用户表中。
3. 计费与订阅
永远不要使用像 is_active 这样的简单布尔值。这会导致数据混乱。
为订阅使用状态机。常见的状态包括: • trialing • active • past_due • canceled • expired • incomplete
这让你能够处理支付失败和宽限期,而无需手动修复数据。
4. 金额与发票
请遵循以下严格规则以避免财务错误:
• 永远不要使用 FLOAT 或 REAL 来处理金额。使用整数来存储分(cents)。例如,$29.99 变为 2999。
• 使用 invoice_line_items 表。你需要它来进行税务报告和退款。
• 如果你根据客户使用产品的程度进行收费,请使用 usage_events 表。
5. 性能优化技巧
• 为外键建立索引。
• 为状态列建立索引。
• 为时间戳列建立索引。
• 避免 N+1 查询。使用 JOIN 在一次查询中获取组织和订阅数据。
一个好的模式在正常工作时是无感的,但在失效时则是灾难性的。
为组织而构建。使用状态机。以整数形式存储金额。
Optional learning community: https://t.me/GyaanSetuAi
