题干与适用场景
这道系统设计题适合平台、后端和 SaaS 基础设施岗位。计费系统发出计划与支付事件,产品服务需要回答“租户 T 的主体 U 是否可以使用功能 F”。假设 50,000 个租户、1,000 万主体、峰值每秒 100,000 次决策请求,月可用性目标 99.99%。取消或暂停后的授权不能无限期继续生效,但计费故障也不能拖垮所有读取路径。
面试官考察点
- 能否把计费作为商业事实源,把授权快照作为读取模型。
- 是否定义租户与主体隔离,以及计划、加购、试用和拒绝规则的优先级。
- 能否处理事件乱序、缓存陈旧、撤销延迟和故障时放行或拒绝的取舍。
- 是否提供版本化 API、审计记录、可观测性与可重放恢复路径。
回答前需要澄清的问题
确认决策按租户、用户、服务账号还是席位;功能能否只给子集;取消后多久必须撤销;是否包含用量配额;每次决策是否需要可解释原因。确认计费事件是否至少一次投递、能否乱序到达。这些答案会改变快照结构、事件处理、缓存 TTL 和故障策略。
30 秒回答框架
我会保留计费为权威源,构建按租户、主体范围、功能和版本索引的授权投影。写入链路消费去重且按版本处理的订阅事件,计算新快照并发布失效通知。读取 API 按明确优先级评估快照,返回允许、拒绝、原因和版本。区域缓存服务热点读取,撤销栅栏或版本栅栏限制陈旧授权。低风险功能才允许有限时间放行;付费或安全敏感功能故障时拒绝,并提供恢复路径。所有变更和决策都可审计。
分步骤深入解答
- 定义契约。
Evaluate(tenantid, subjectid, feature, context)返回决策、原因码、快照版本和过期时间。上下文可包含计划、区域、席位或灰度属性;OpenFeature 要求唯一 targeting key,并支持自定义字段,不应把计费状态塞进一个无结构字符串。 - 保存不可变授权事实。 记录订阅产品、加购、试用、席位、起止时间和显式拒绝等带版本事实。投影保存解析后的功能集合及来源事实 ID。暂停或合规拒绝覆盖普通授权;试用到期只改变当前投影,不改历史。
- 构建传播链路。 计费事件带租户、订阅版本、事件 ID 和生效时间。inbox 去重事件 ID,拒绝旧版本,并在事务中写入事实与投影。outbox 发布
entitlementversionchanged,消费者按租户和功能失效缓存。事实可重放以重建损坏投影。 - 提供读取。 无状态评估 API 读取本地缓存或区域存储。缓存键包含租户、主体范围、功能和策略版本;条目携带投影版本与过期时间。请求带有更新版本栅栏时,缓存落后就回源到权威区域存储。
- 按风险选择一致性。 设定可测的撤销 SLO,例如普通取消 60 秒,欺诈或安全暂停接近即时。把拒绝栅栏写入强可达存储;服务拒绝早于栅栏的缓存允许。不要在不付同步成本的情况下承诺零陈旧读取。
- 处理故障与扩展。 按租户分区事件以保持租户内顺序,按租户哈希分片投影,并隔离热点租户。计费延迟时暴露最后应用版本并告警。缓存或区域存储故障时,只有低风险功能使用有界陈旧窗口;高风险功能返回有类型的依赖错误,不静默放行。
- 审计与验证。 记录谁改了计划、哪个事件版本生成投影、决策依据。监控事件延迟、投影年龄、缓存命中率、陈旧允许拦截、决策延迟和跨租户授权失败。测试乱序、重复投递、时钟偏差、请求中途取消、租户迁移和空投影重放。
高质量示范回答
我会把商业事实和版本化授权投影分开。计费事件携带事件 ID、租户、订阅版本、生效时间和变更产品。inbox 去重并拒绝旧版本,然后在事务里写事实、解析后的功能快照和 outbox 通知。评估 API 返回允许或拒绝、原因、投影版本和过期时间。缓存键必须包含租户和主体范围,防止客户之间串读。
关键取舍是撤销。我会给普通取消设 60 秒 SLO,为欺诈或安全暂停发布拒绝栅栏。每个缓存允许携带投影版本;发现更新栅栏就回源区域存储。低风险界面功能在存储故障时可使用有限陈旧窗口,而付费数据导出或安全控制应拒绝并返回有类型依赖错误。审计记录关联每个决策的事件和策略版本,重放任务可从不可变事实重建投影。
常见错误
- 每次请求同步读取计费表 → 支付延迟和故障变成授权故障 → 将不可变事实投影为读优化快照。
- 只按功能缓存 → 可能把其他租户或主体的决策返回给当前请求 → 键中加入租户、主体范围和策略版本。
- 按到达顺序应用事件 → 旧取消或续订覆盖新状态 → 去重事件 ID 并拒绝低于当前版本的事件。
- 承诺处处即时撤销 → 隐藏网络和缓存成本 → 声明可测撤销 SLO,并执行拒绝栅栏。
- 付费或安全功能故障时放行 → 陈旧授权变成收入或安全事故 → 按风险分类,高风险必须拒绝。
追问及应对
如何只给租户 10% 的用户开放功能?
把商业授权和灰度选择分开。授权快照说明租户拥有功能,带稳定主体 targeting key 的评估上下文负责灰度。记录两次决策,让支持人员能区分“没购买”和“灰度未选中”。
取消事件延迟到达怎么办?
暴露投影年龄和事件延迟,在撤销 SLO 前告警;若已有计费版本或拒绝栅栏就直接使用。不要从缺失心跳推断取消。事件到达后幂等应用,并让受影响范围全部失效。
如何迁移租户分片?
在租户元数据写入迁移 epoch,有限切换期内双读,并发布栅栏阻止旧分片继续放行。核对计数、版本和抽样决策后再删除旧副本;保留事实以便回滚。