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 核心设计目标

目标说明挑战
一致性全局权限视图跨数据中心复制
低延迟P99 < 10ms复杂关系计算
高可用> 99.999%故障转移
全球复制多区域部署一致性协议
灵活模型支持任意关系表达能力强

二、核心数据结构

2.1 Relation Tuple(关系元组)

Zanzibar 的核心数据模型是 Relation Tuple:

flowchart LR
    subgraph "Relation Tuple"
        N[namespace]
        O[object_id]
        R[relation]
        S[subject]
    end
    
    N -->|"doc"| O
    O -->|"report-123"| R
    R -->|"viewer"| S
    S -->|"user:alice"|
    
    style N fill:#e3f2fd
    style O fill:#e8f5e9
    style R fill:#fff3e0
    style S fill:#fce4ec
字段类型说明
namespacestring名称空间(如 docfolder
object_idstring对象标识
relationstring关系类型(如 ownereditor
subjectSubject主语(可以是用户或群组)

2.2 Subject(主语)

Subject 可以是用户或群组:

Subject
{
  "subject": {
    "oneof": {
      "user": { "user_id": "alice" },
      "group": {
        "group_id": "engineering",
        "namespace": "group"
      }
    }
  }
}

群组本身可以有成员关系,形成层级结构:

user:alice ∈ group:engineering
group:engineering ∈ group:all-employees

2.3 示例数据

Zanzibar
[
  {
    "namespace": "doc",
    "object_id": "report-2024",
    "relation": "owner",
    "subject": { "user": { "user_id": "alice" } }
  },
  {
    "namespace": "doc",
    "object_id": "report-2024",
    "relation": "editor",
    "subject": { "group": { "group_id": "engineering", "namespace": "group" } }
  },
  {
    "namespace": "group",
    "object_id": "engineering",
    "relation": "member",
    "subject": { "user": { "user_id": "bob" } }
  },
  {
    "namespace": "group",
    "object_id": "engineering",
    "relation": "member",
    "subject": { "user": { "user_id": "charlie" } }
  }
]

三、权限模型

3.1 直接权限检查

检查用户是否与对象有直接关系:

sequenceDiagram
    Client->>Zanzibar: Check(doc:report-2024#viewer@user:alice)
    Zanzibar->>Storage: Lookup tuple
    Storage-->>Zanzibar: Found tuple
    Zanzibar-->>Client: ALLOWED

3.2 群组权限检查

通过群组间接获得权限:

user:alice ∈ group:engineering
doc:report-2024#editor@group:engineering
───────────────────────────────
user:alice can edit doc:report-2024
flowchart LR
    Alice[user:alice] -->|member| Eng[group:engineering]
    Eng -->|editor| Doc[doc:report-2024]
    
    Alice -.->|派生| edit_doc

3.3 关系类型定义

Namespace
{
  "name": "doc",
  "relation_definitions": [
    {
      "name": "owner",
      "userset_rewrite": { "union": { "root": [] } }
    },
    {
      "name": "editor",
      "userset_rewrite": {
        "union": {
          "root": [
            { "computed": { "relation": "owner" } },
            { "tupleToUserset": { "tupleset": "parent", "computedUserset": { "relation": "editor" } } }
          ]
        }
      }
    },
    {
      "name": "viewer",
      "userset_rewrite": {
        "union": {
          "root": [
            { "computed": { "relation": "editor" } },
            { "computed": { "relation": "owner" } },
            { "tupleToUserset": { "tupleset": "parent", "computedUserset": { "relation": "viewer" } } }
          ]
        }
      }
    },
    {
      "name": "parent",
      "relation_reference": { "namespace": "folder" }
    }
  ]
}

3.4 Computed Userset

直接从其他关系继承权限:

{
  "computed": {
    "relation": "owner"  // viewer 继承 owner 的所有主体
  }
}

3.5 TupleToUserset

通过元组动态计算权限主体:

{
  "tupleToUserset": {
    "tupleset": "parent",           // 查找 parent 关系
    "computedUserset": {
      "relation": "editor"          // 使用找到的对象的 editor 关系
    }
  }
}

含义:如果 folder:project#editor@group:alice-team,则 doc:readme#viewer@group:alice-team(继承父文件夹的 editor 权限)。

四、一致性模型

4.1 Zooke's Law 挑战

分布式系统面临一个基本权衡:一致性 vs 延迟

延迟越低 → 允许更大的不一致窗口
延迟越高 → 可以提供更强的一致性保证

4.2 快照读取 vs 即时读取

模式一致性延迟场景
Snapshot Read固定时间点历史权限查询
Immediate Read写入后立即可读一般场景
Linearized Read全局顺序保证关键操作

4.3 ZooKeeper 的教训

Google 早期使用 ZooKeeper 管理权限,发现:

  • 写入瓶颈:ZooKeeper 的 leader 成为写入热点
  • 扩展困难:无法水平扩展
  • 延迟高:P99 延迟达数百毫秒

4.4 Spanner 的解决方案

Zanzibar 底层使用 Google Spanner 数据库:

  • 全球分布式的强一致性数据库
  • 基于 TrueTime(GPS + 原子钟)
  • 提供全局有序的事务
flowchart TB
    subgraph "Spanner 集群"
        subgraph "区域 1 (美东)"
            O1[副本 1]
            O2[副本 2]
        end
        subgraph "区域 2 (欧洲)"
            O3[副本 3]
            O4[副本 4]
        end
        subgraph "区域 3 (亚太)"
            O5[副本 5]
            O6[副本 6]
        end
    end
    
    O1 --> O2
    O3 --> O4
    O5 --> O6
    
    style O1 fill:#e3f2fd
    style O3 fill:#e3f2fd
    style O5 fill:#e3f2fd

五、架构设计

5.1 系统架构

flowchart TB
    subgraph "客户端"
        SDK[SDK]
    end
    
    subgraph "Zanzibar 服务层"
        API[API Server]
        PG[Permission Graph]
        AC[ACL Cache]
    end
    
    subgraph "存储层"
        NHP[Namespace Health Polcies]
        TN[Tuple Store]
        NS[Namespace Store]
    end
    
    SDK --> API
    API --> PG
    API --> AC
    PG --> TN
    PG --> NS
    NHP -.->|配置| PG
    
    style SDK fill:#e8f5e9
    style API fill:#e3f2fd
    style TN fill:#fff3e0

5.2 核心组件

组件职责
API Server处理客户端请求路由
Permission Graph权限计算引擎
ACL Cache权限结果缓存
Tuple Store关系元组持久化
Namespace Store命名空间配置存储

5.3 写入流程

sequenceDiagram
    participant C as Client
    participant API as API Server
    participant PG as Permission Graph
    participant S as Spanner
    
    C->>API: Write Tuple
    API->>PG: Prepare Write
    PG->>S: Begin Transaction
    S-->>PG: Transaction OK
    PG->>S: Write Tuple
    PG->>S: Commit
    S-->>PG: Committed
    PG-->>API: Write Success
    API-->>C: Write Success
    
    Note over PG,C: 缓存失效通知
    PG->>AC: Invalidate Cache

5.4 读取流程

sequenceDiagram
    participant C as Client
    participant API as API Server
    participant AC as ACL Cache
    participant PG as Permission Graph
    participant S as Spanner
    
    C->>API: Check Permission
    API->>AC: Lookup Cache
    AC-->>API: Cache Hit?
    
    alt Cache Miss
        API->>PG: Compute Permission
        PG->>S: Lookup Tuples
        S-->>PG: Return Tuples
        PG-->>API: Permission Result
        API->>AC: Cache Result
    else Cache Hit
        API-->>C: Permission Result
    end

六、Watch API 与实时通知

6.1 Watch 机制

Zanzibar 支持订阅权限变更:

Watch
rpc WatchChanges(WatchRequest) returns (stream WatchResponse) {}

message WatchRequest {
    string namespace_filter = 1;
    string object_id_filter = 2;
    int64 start_read_offset = 3;  // 从哪个时间点开始
}

message WatchResponse {
    repeated RelationshipUpdate updates = 1;
    int64 read_offset = 2;
}

6.2 应用场景

场景说明
缓存同步权限变更时主动更新缓存
审计日志记录所有权限变更
实时通知用户权限变更时发送通知
跨系统同步其他系统同步权限状态

七、性能数据

7.1 论文中的性能指标

指标数值
全球请求量每天数十亿次
峰值 QPS数百万
P50 延迟2ms
P99 延迟10ms
P99.9 延迟100ms
可用性99.999%

7.2 性能优化策略

缓存层设计

flowchart LR
    subgraph "L1: 本地缓存"
        MC[Memcache]
    end
    
    subgraph "L2: 分布式缓存"
        RC[Redis Cluster]
    end
    
    subgraph "L3: 数据库"
        DB[(Spanner)]
    end
    
    Request --> MC
    MC -.->|miss| RC
    RC -.->|miss| DB

缓存失效策略

  • 写时失效(Write-through Invalidation)
  • 版本号控制
  • 渐进过期

八、启发与局限

8.1 Zanzibar 的核心贡献

贡献影响
全球一致的权限系统证明了大规模 ReBAC 的可行性
灵活的关系模型支持任意复杂的权限场景
一致性与延迟权衡提供了可配置的一致性级别
开源实现参考OpenFGA 等项目借鉴其设计

8.2 局限性

局限说明
运维复杂度全球分布式系统的运维挑战
延迟下界即使有缓存,最慢情况仍达 100ms
表达能力不支持数值比较(如 amount < 10000
运维成本需要专业团队维护

8.3 开源实现

基于 Zanzibar 论文的开源实现:

项目特点
OpenFGAAuth0 出品,Zanzibar 的轻量实现
Casbin支持多种模型,社区活跃
OPA通用策略引擎,可与 Zanzibar 概念结合
核心洞察

Zanzibar 的精髓不在于某个具体技术,而在于将复杂的关系计算转化为可扩展的分布式系统问题。它证明了:只要架构设计得当,即使是「用户 A 能否访问资源 B」这样看似简单的问题,也可以优雅地解决。

思考题

问题 1:Zanzibar 的「一致性 vs 延迟」权衡对实际业务系统设计有什么启示?

参考答案

核心启示:

1. 不同操作需要不同一致性级别

  • 权限检查:可以使用「稍旧」的数据(P99 10ms)
  • 权限写入:需要强一致性
  • 管理员操作:可以接受更高延迟

2. 一致性是可配置的

  • 根据业务需求选择合适的一致性级别
  • 关键操作使用强一致性
  • 普通操作使用最终一致性

3. 缓存是性能的关键

  • 多级缓存架构
  • 写时失效策略
  • 版本号控制并发

4. 接受不完美

  • 没有完美的系统
  • 权衡是设计的核心
  • 满足业务需求优先

问题 2:如果让你设计一个类似 Zanzibar 的系统,你会如何选择存储层?请比较几种可能的方案。

参考答案

存储层方案对比:

方案优点缺点适用场景
Spanner强一致,全球分布成本高,需要 GCP大型互联网公司
CockroachDB开源,强一致延迟较高自建团队
TiDBMySQL 兼容,强一致生态较新MySQL 用户迁移
Cassandra高可用,写吞吐高最终一致写入密集型
etcd强一致,成熟扩展性有限中小规模
自研完全可控开发成本高有特殊需求

推荐方案

  • 初创公司:使用 OpenFGA(云服务)快速验证
  • 中型公司:CockroachDB + 应用层缓存
  • 大型公司:参考 Zanzibar 设计自研