Google Zanzibar 论文解析
2019 年,Google 发表了一篇震撼业界的论文:《Zanzibar: Google's Consistent, Global Authorization System》。这篇论文描述了 Google 内部使用了 10 年的权限系统,它支撑着 YouTube、Google Drive、Google Cloud 等数十亿用户产品的授权决策。
一个每秒处理数百万请求、全球分布式部署、保证强一致性、同时支持毫秒级延迟的权限系统——它是如何做到的?
一、背景与设计目标
1.1 Google 的权限挑战
Google 的产品有一个独特之处:跨服务的统一授权。
当你在 YouTube 上分享一个视频给特定用户时,这个授权决策需要在 YouTube、Gmail、Google Drive 等多个系统中生效。传统的「每个服务自己管理权限」模式无法满足需求。
1.2 核心设计目标
二、核心数据结构
2.1 Relation Tuple(关系元组)
Zanzibar 的核心数据模型是 Relation Tuple:
2.2 Subject(主语)
Subject 可以是用户或群组:
群组本身可以有成员关系,形成层级结构:
2.3 示例数据
三、权限模型
3.1 直接权限检查
检查用户是否与对象有直接关系:
3.2 群组权限检查
通过群组间接获得权限:
3.3 关系类型定义
3.4 Computed Userset
直接从其他关系继承权限:
3.5 TupleToUserset
通过元组动态计算权限主体:
含义:如果 folder:project#editor@group:alice-team,则 doc:readme#viewer@group:alice-team(继承父文件夹的 editor 权限)。
四、一致性模型
4.1 Zooke's Law 挑战
分布式系统面临一个基本权衡:一致性 vs 延迟。
4.2 快照读取 vs 即时读取
4.3 ZooKeeper 的教训
Google 早期使用 ZooKeeper 管理权限,发现:
- 写入瓶颈:ZooKeeper 的 leader 成为写入热点
- 扩展困难:无法水平扩展
- 延迟高:P99 延迟达数百毫秒
4.4 Spanner 的解决方案
Zanzibar 底层使用 Google Spanner 数据库:
- 全球分布式的强一致性数据库
- 基于 TrueTime(GPS + 原子钟)
- 提供全局有序的事务
五、架构设计
5.1 系统架构
5.2 核心组件
5.3 写入流程
5.4 读取流程
六、Watch API 与实时通知
6.1 Watch 机制
Zanzibar 支持订阅权限变更:
6.2 应用场景
七、性能数据
7.1 论文中的性能指标
7.2 性能优化策略
缓存层设计:
缓存失效策略:
- 写时失效(Write-through Invalidation)
- 版本号控制
- 渐进过期
八、启发与局限
8.1 Zanzibar 的核心贡献
8.2 局限性
8.3 开源实现
基于 Zanzibar 论文的开源实现:
Zanzibar 的精髓不在于某个具体技术,而在于将复杂的关系计算转化为可扩展的分布式系统问题。它证明了:只要架构设计得当,即使是「用户 A 能否访问资源 B」这样看似简单的问题,也可以优雅地解决。
思考题
问题 1:Zanzibar 的「一致性 vs 延迟」权衡对实际业务系统设计有什么启示?
参考答案
核心启示:
1. 不同操作需要不同一致性级别
- 权限检查:可以使用「稍旧」的数据(P99 10ms)
- 权限写入:需要强一致性
- 管理员操作:可以接受更高延迟
2. 一致性是可配置的
- 根据业务需求选择合适的一致性级别
- 关键操作使用强一致性
- 普通操作使用最终一致性
3. 缓存是性能的关键
- 多级缓存架构
- 写时失效策略
- 版本号控制并发
4. 接受不完美
- 没有完美的系统
- 权衡是设计的核心
- 满足业务需求优先
问题 2:如果让你设计一个类似 Zanzibar 的系统,你会如何选择存储层?请比较几种可能的方案。
参考答案
存储层方案对比:
推荐方案:
- 初创公司:使用 OpenFGA(云服务)快速验证
- 中型公司:CockroachDB + 应用层缓存
- 大型公司:参考 Zanzibar 设计自研