从 RBAC 到 OpenFGA:细粒度授权的架构、落地与取舍

Posted on 四 05 3月 2026 in Tech

Abstract 从 RBAC 到 OpenFGA:细粒度授权的架构、落地与取舍
Authors Walter Fan
Category tech note
Status v1.0
Updated 2026-03-05
License CC-BY-NC-ND 4.0

从 RBAC 到 OpenFGA:细粒度授权的架构、落地与取舍

写了二十多年代码,我越来越觉得:认证(Authentication)是一道门,授权(Authorization)是一栋楼里的每一把锁。门只需要装一道,但锁要一间一间配,漏一间就是安全事故。

RBAC(Role-Based Access Control)是这栋楼里最常见的锁——简单、标准、够用。但当你的楼从一栋变成一个园区,从固定住户变成随时来去的访客,RBAC 就开始吃力了。

这篇文章从 RBAC 的局限出发,聊聊 OpenFGA 这把"新锁"——它的架构设计、落地路径、以及商业公司在"用开源"还是"自己造"之间的取舍。


一、RBAC:老黄牛的能力边界

1.1 RBAC 的核心模型

RBAC 的思路很直白:用户 → 角色 → 权限

flowchart LR
    User["User 用户"] --> Role["Role 角色"] --> Permission["Permission 权限"]
    Permission --> AR["Action × Resource<br/>(操作 × 资源)"]

一个典型的 RBAC 表结构:

-- 用户-角色关联
CREATE TABLE user_roles (
    user_id    BIGINT NOT NULL,
    role_id    BIGINT NOT NULL,
    PRIMARY KEY (user_id, role_id)
);

-- 角色-权限关联
CREATE TABLE role_permissions (
    role_id       BIGINT NOT NULL,
    permission_id BIGINT NOT NULL,
    PRIMARY KEY (role_id, permission_id)
);

-- 权限定义
CREATE TABLE permissions (
    id       BIGINT PRIMARY KEY,
    action   VARCHAR(50),   -- read, write, delete
    resource VARCHAR(100)   -- document, order, user
);

RBAC 的优势很明显:

  • 概念简单:产品经理、运维、审计都能理解
  • 实现成熟:Spring Security、Django Permission、Casbin 都有现成支持
  • 审计友好:谁有什么角色、角色有什么权限,一目了然
  • NIST 标准:RBAC 有 NIST INCITS 359-2004 标准,合规友好

1.2 RBAC 的三个痛点

但当系统复杂到一定程度,RBAC 的三个痛点就会暴露:

痛点一:角色爆炸(Role Explosion)

假设你有一个文档管理系统,需要控制:

  • 3 个部门(工程、产品、市场)
  • 4 种操作(查看、编辑、评论、删除)
  • 2 个数据范围(本部门、全公司)

纯 RBAC 需要 3 × 4 × 2 = 24 个角色。再加上项目维度、层级维度,角色数量指数增长。我见过一个企业系统有 800+ 个角色,没人说得清每个角色到底能干什么。

痛点二:无法表达资源间的关系

RBAC 回答的是"Alice 有 editor 角色",但回答不了"Alice 是 这个文件夹 的 editor,所以她也能编辑 文件夹里的文档"。

这种层级继承(Hierarchical Inheritance)在 Google Drive、GitHub、Notion 等产品中无处不在,但 RBAC 天然不支持。你要么在业务代码里硬编码继承逻辑,要么给每个资源单独分配角色——两种方案都很痛苦。

痛点三:动态共享难以建模

"Alice 把文档分享给 Bob,Bob 可以查看但不能编辑"——这是一个 实例级别 的权限,不是角色能覆盖的。RBAC 要实现这个,通常需要引入 ACL(Access Control List),但 ACL 和 RBAC 混用会让系统变得很难维护。

RBAC 能回答的问题:
  ✅ Alice 是管理员吗?
  ✅ 管理员能删除用户吗?

RBAC 回答不了的问题:
  ❌ Alice 能编辑 **这个** 文档吗?(实例级)
  ❌ Alice 是这个文件夹的 editor,她能编辑文件夹里的文档吗?(继承)
  ❌ Bob 被 Alice 分享了这个文档,他能查看吗?(动态共享)

二、Google Zanzibar:巨人的答案

2019 年,Google 发表了 Zanzibar 论文,揭示了 Google Drive、YouTube、Google Cloud 等产品背后的统一授权系统。

Zanzibar 的核心思想只有一个:一切权限都是关系(Relationship)

flowchart LR
    subgraph RBAC["传统 RBAC"]
        direction LR
        U[User] --> R[Role] --> P[Permission] --> Res[Resource]
    end
    subgraph ReBAC["Zanzibar / ReBAC"]
        direction LR
        S["Subject (谁)"] -->|"relation (什么关系)"| O["Object (什么东西)"]
    end

一条关系元组(Relationship Tuple)长这样:

document:readme#editor@user:alice

翻译成人话:Alice 是 readme 文档的 editor

这种模型的威力在于:关系可以 组合和继承

# Alice 是 engineering 文件夹的 editor
folder:engineering#editor@user:alice

# readme 文档在 engineering 文件夹里
document:readme#parent@folder:engineering

# 授权模型定义:文档的 editor 包括其父文件夹的 editor
type document
  relations
    define parent: [folder]
    define editor: [user] or editor from parent

现在问"Alice 能编辑 readme 吗?",Zanzibar 会沿着关系图遍历:

flowchart LR
    Alice["user:alice"] -->|editor| Folder["folder:engineering"]
    Folder -->|"parent of"| Doc["document:readme"]
    Doc -.->|"沿关系推导"| Result["结论:Alice 是 readme 的 editor ✅"]

这就是 ReBAC(Relationship-Based Access Control) 的核心——权限不是静态分配的,而是通过关系图动态推导的。


三、OpenFGA 架构深度剖析

OpenFGA 是 Auth0/Okta 开源的 Zanzibar 实现,现为 CNCF Sandbox 项目。已被 Grafana Labs、Canonical(Ubuntu)、Docker、Agicap、Read.AI 等公司采用。

3.1 整体架构

flowchart TB
    subgraph App["应用层"]
        SA[Service A]
        SB[Service B]
        SC[Service C]
        SDK["OpenFGA SDK (gRPC/HTTP)"]
        SA --> SDK
        SB --> SDK
        SC --> SDK
    end
    subgraph Server["OpenFGA Server"]
        API["API Layer<br/>(HTTP/gRPC)"]
        QE["Query Engine<br/>(图遍历)"]
        CT["Change Tracker<br/>(变更日志)"]
        Storage["Storage Adapter<br/>PostgreSQL / MySQL / SQLite(beta) / In-Memory"]
        API --> Storage
        QE --> Storage
        CT --> Storage
    end
    SDK --> API
    SDK --> QE
    SDK --> CT

3.2 核心概念

概念 说明 示例
Store 隔离的授权数据空间,类似数据库 每个租户一个 Store
Authorization Model 定义类型、关系和权限推导规则 DSL 文件
Type 实体类型 user, document, folder
Relation 类型之间的命名关系 editor, viewer, parent
Tuple 具体的关系实例 document:readme#editor@user:alice
Condition 基于上下文的条件约束(ABAC 能力) ipAddress in allowedRange

3.3 核心 API

OpenFGA 只有 6 个核心 API,设计极其克制(另有 CreateStore、ReadChanges 等管理接口):

mindmap
  root((OpenFGA API))
    写入类
      Write 写入/删除关系元组
      WriteModel 更新授权模型
    查询类
      Check 检查某用户是否有某权限
      ListObjects 列出用户有权访问的对象
      ListUsers 列出对某对象有权限的用户
      Expand 展开权限推导路径 调试用
    管理类
      CreateStore 创建 Store
      ReadChanges 读取变更日志 审计/同步

其中最关键的是 Check() — 它是所有授权决策的入口:

from openfga_sdk import OpenFgaClient, ClientConfiguration
from openfga_sdk.client.models import ClientCheckRequest

config = ClientConfiguration(
    api_url="http://localhost:8080",
    store_id="your-store-id",
    authorization_model_id="your-model-id"
)

async with OpenFgaClient(config) as client:
    response = await client.check(ClientCheckRequest(
        user="user:alice",
        relation="editor",
        object="document:readme"
    ))
    print(response.allowed)  # True or False

3.4 授权模型 DSL

OpenFGA 的 DSL 是其最精妙的设计。一个 Google Drive 风格的模型:

model
  schema 1.1

type user

type organization
  relations
    define admin: [user]
    define member: [user] or admin

type folder
  relations
    define org: [organization]
    define owner: [user]
    define editor: [user] or owner or admin from org
    define viewer: [user] or editor or member from org

type document
  relations
    define parent: [folder]
    define owner: [user]
    define editor: [user] or owner or editor from parent
    define viewer: [user] or editor or viewer from parent
    define can_share: owner
    define blocked: [user]
    define can_view: viewer but not blocked
    define can_edit: editor but not blocked

这个模型表达了:

  1. 组织层级:admin 自动是 member
  2. 文件夹权限:org 的 admin 自动是文件夹的 editor
  3. 文档继承:文档继承父文件夹的权限
  4. 显式拒绝:被 blocked 的用户即使有其他权限也无法访问
  5. 分享控制:只有 owner 能分享文档

3.5 图遍历引擎

Check() 的核心是一个 有向图遍历 算法。当你问"Alice 能编辑 document:readme 吗?",引擎会沿 editor: [user] or owner or editor from parent 分支搜索:

flowchart TB
    Q["Alice 能编辑 document:readme 吗?"] --> D1{"直接关系?<br/>document:readme#editor@user:alice"}
    Q --> O1{"owner 关系?<br/>Alice 是 readme 的 owner?"}
    Q --> P1{"继承关系?<br/>parent folder 的 editor 含 Alice?"}
    P1 --> F["找到 folder:engineering"]
    F --> D2{"直接关系?"}
    F --> O2{"owner 关系?"}
    F --> A2{"org admin 关系?<br/>→ 递归继续遍历"}
    D1 & O1 & D2 & O2 & A2 -.->|"任一分支 true"| R["最终结果 true ✅"]

(任一分支返回 true 即短路返回,最终结果为 true。)

这个遍历有几个关键优化:

  • 并发遍历:多个分支并行检查,任一成功即短路返回
  • 缓存:热点元组和中间结果缓存
  • 深度限制:防止无限递归(默认最大深度 25)
  • 超时控制:单次 Check 有超时限制

四、RBAC vs ReBAC:不是替代,是演进

很多人问:用了 OpenFGA 是不是就不需要 RBAC 了?不是

flowchart LR
    Left["简单 / 粗粒度"] --- ACL["ACL<br/>(列表)"] --> RBAC["RBAC<br/>(角色)"] --> ABAC["ABAC<br/>(属性)"] --> ReBAC["ReBAC<br/>(关系)"] --- Right["灵活 / 细粒度"]
    style Left fill:#fff,stroke-dasharray:5 5
    style Right fill:#fff,stroke-dasharray:5 5

一条轴线看懂:从左到右,由简单、粗粒度走向灵活、细粒度

维度 RBAC ReBAC (OpenFGA)
核心抽象 角色 关系
粒度 资源类型级 资源实例级
继承 角色继承(有限) 关系图遍历(灵活)
动态共享 需要额外 ACL 原生支持
性能 O(1) 查表 O(n) 图遍历
复杂度 中高
适用场景 后台管理、API 网关 文档协作、多租户 SaaS
学习曲线

我的建议:大多数系统应该 RBAC + ReBAC 混合使用

  • 粗粒度(API 级别):用 RBAC。"只有 admin 能访问 /admin/* 接口"——简单直接。
  • 细粒度(资源级别):用 ReBAC。"Alice 能编辑这个文档吗?"——需要关系推导。
# 两层授权的伪代码
@app.route("/api/documents/<doc_id>", methods=["PUT"])
@require_role("editor")  # 第一层:RBAC,粗粒度
async def update_document(doc_id):
    # 第二层:ReBAC,细粒度
    allowed = await fga_client.check(
        user=f"user:{current_user.id}",
        relation="editor",
        object=f"document:{doc_id}"
    )
    if not allowed:
        return {"error": "Forbidden"}, 403
    # ... 业务逻辑

五、商业公司落地路径

5.1 渐进式迁移策略

不要试图一步到位。我建议分四个阶段:

flowchart LR
    P1["Phase 1 · 评估与 PoC (2-4 周)<br/>建模 / 原型验证 / 性能测试"]
    P2["Phase 2 · 影子模式 (4-8 周)<br/>双写双读 / 对比结果 / 不影响线上"]
    P3["Phase 3 · 逐步切换 (8-16 周)<br/>新功能用 FGA / 旧功能保持 / 逐步切换"]
    P4["Phase 4 · 全面迁移 (持续)<br/>旧功能迁移 / 下线旧系统"]
    P1 --> P2 --> P3 --> P4

Phase 1:评估与 PoC(2-4 周)

  • 梳理现有权限模型,识别 RBAC 覆盖不了的场景
  • 用 OpenFGA Playground 建模,验证能否表达业务需求
  • 做性能基准测试:Check() 延迟、Write() 吞吐量

Phase 2:影子模式(4-8 周)

这是最关键的一步。在不影响线上的前提下验证正确性:

async def check_permission(user, action, resource):
    # 旧系统做决策(线上生效)
    old_result = rbac_check(user, action, resource)

    # 新系统做决策(仅记录,不生效)
    new_result = await fga_check(user, action, resource)

    # 对比结果
    if old_result != new_result:
        logger.warning(f"Authorization mismatch: "
                      f"user={user}, action={action}, resource={resource}, "
                      f"old={old_result}, new={new_result}")
        metrics.increment("authz.mismatch")

    return old_result  # 仍然用旧系统的结果

Phase 3:逐步切换(8-16 周)

  • 新功能直接用 OpenFGA
  • 旧功能按模块逐步切换,每次切换一个模块
  • 保留回滚开关(Feature Flag)

Phase 4:全面迁移(持续)

  • 下线旧的 RBAC 表和代码
  • 建立授权模型的 CI/CD 流程
  • 完善监控和告警

5.2 数据同步:最容易踩的坑

OpenFGA 的关系元组需要和业务数据保持一致。这是落地中 最容易出问题 的地方。

flowchart LR
    E1["用户加入团队"] --> W1["Write(team:X#member@user:alice)"]
    E2["用户离开团队"] --> D2["Delete(team:X#member@user:alice)"]
    E3["文档移动到新文件夹"] --> M3["Delete(doc:Y#parent@folder:old)<br/>Write(doc:Y#parent@folder:new)"]
    E4["文档被删除"] --> D4["Delete(doc:Y 相关的所有元组)"]

三种同步方案

方案 一致性 复杂度 适用场景
同步写入(业务操作和 FGA 写入在同一事务) 强一致 高(分布式事务) 金融、医疗
事件驱动(业务写 DB → 发事件 → Consumer 写 FGA) 最终一致 大多数场景
定时全量同步(定期从业务 DB 全量导入 FGA) 弱一致 PoC、非关键场景

我推荐大多数公司用 事件驱动 方案,配合幂等写入和补偿机制:

# Kafka Consumer 示例
async def handle_team_member_event(event):
    if event.type == "MEMBER_ADDED":
        await fga_client.write(writes=[
            ClientTupleKey(
                user=f"user:{event.user_id}",
                relation="member",
                object=f"team:{event.team_id}"
            )
        ])
    elif event.type == "MEMBER_REMOVED":
        await fga_client.write(deletes=[
            ClientTupleKeyWithoutCondition(
                user=f"user:{event.user_id}",
                relation="member",
                object=f"team:{event.team_id}"
            )
        ])

5.3 性能考量

OpenFGA 的 Check() 延迟取决于关系图的深度和宽度。根据官方基准和社区反馈:

场景 典型延迟 说明
直接关系 < 5ms document:X#editor@user:alice 直接匹配
一层继承 5-15ms 需要查一次 parent
多层继承 15-50ms 3-4 层嵌套
复杂模型 50-200ms 多个 union/intersection/exclusion

优化手段

  1. 控制模型深度:继承层级不超过 3-4 层
  2. 合理使用 ListObjects:批量查询比逐个 Check 高效
  3. 客户端缓存:对变化不频繁的权限做短时缓存(TTL 30-60s)
  4. 水平扩展:OpenFGA Server 无状态,可以水平扩展
  5. 数据库优化:PostgreSQL 配合连接池和索引优化

六、风险分析

6.1 技术风险

风险 影响 缓解措施
OpenFGA 服务不可用 所有授权决策失败 多副本部署 + 客户端缓存 + 降级策略(fail-open 或 fail-close)
数据不一致 权限判断错误 事件驱动 + 补偿任务 + 定期全量校验
模型变更导致权限变化 意外的权限放大或收缩 模型版本管理 + 影子模式验证 + 回滚机制
性能退化 接口延迟增加 监控 P99 延迟 + 告警 + 缓存 + 限制模型复杂度
关系元组膨胀 存储和查询压力 定期清理孤儿元组 + 监控元组数量

6.2 组织风险

  • 学习曲线:ReBAC 的思维方式和 RBAC 不同,团队需要时间适应。建议先做内部培训和 Workshop。
  • 运维负担:多了一个有状态服务(OpenFGA + PostgreSQL),需要 DBA 和 SRE 支持。
  • 供应商锁定:虽然 OpenFGA 是开源的,但如果深度集成后迁移成本很高。
  • 社区成熟度:OpenFGA 是 CNCF Sandbox 项目(非 Graduated),社区规模和生态还在成长中。

6.3 降级策略

授权服务是关键路径,必须有降级方案:

async def check_with_fallback(user, relation, obj):
    try:
        result = await asyncio.wait_for(
            fga_client.check(user=user, relation=relation, object=obj),
            timeout=0.5  # 500ms 超时
        )
        return result.allowed
    except (TimeoutError, ConnectionError) as e:
        logger.error(f"OpenFGA unavailable: {e}")
        metrics.increment("authz.fallback")

        # 降级策略选择:
        # 方案 A: fail-close(安全优先,拒绝所有请求)
        # return False

        # 方案 B: fail-open(可用性优先,允许所有请求)
        # return True

        # 方案 C: 回退到本地缓存或旧 RBAC 系统(推荐)
        return local_cache.get(f"{user}:{relation}:{obj}", False)

七、开源 vs 自研:取舍之道

这是每个技术团队都会面临的问题。我把市面上的选择梳理一下:

7.1 开源方案对比

项目 背景 模型 语言 存储 成熟度 商业支持
OpenFGA Auth0/Okta Zanzibar Go PG/MySQL/SQLite CNCF Sandbox Okta FGA (SaaS)
SpiceDB Authzed Zanzibar Go PG/CockroachDB/Spanner 生产就绪 Authzed (SaaS)
Ory Keto Ory Zanzibar Go PG/MySQL Beta Ory Network (SaaS)
Casbin 社区 RBAC/ABAC/ACL Go/多语言 多种 成熟
OPA CNCF 通用策略 Go 无(内存) Graduated Styra (SaaS)

OpenFGA vs SpiceDB 是最常被比较的两个:

  • OpenFGA:Okta 背书,SDK 丰富(Java/Go/Python/Node/.NET),Playground 好用,社区活跃度高。适合已经在用 Auth0/Okta 生态的团队。
  • SpiceDB:API 设计更贴近 Zanzibar 原论文,支持 CockroachDB 和 Spanner(全球分布式),Watch API 更成熟。适合需要全球部署的大规模系统。

7.2 自研的诱惑与代价

我见过不少团队选择自研授权系统,理由通常是:

  • "我们的业务模型很特殊,开源方案不够灵活"
  • "不想引入外部依赖,增加运维复杂度"
  • "我们有能力自己做,而且可以完全掌控"

这些理由都有道理,但自研的代价往往被低估:

mindmap
  root((自研授权系统的成本))
    显性成本(大家都能看到)
      "开发:3-6 个月,2-3 个高级工程师"
      "测试:权限组合爆炸,用例指数增长"
    隐性成本(容易被忽略)
      "性能优化:图遍历 / 缓存 / 并发控制"
      "一致性保证:分布式数据同步"
      "模型演进:schema migration"
      "安全审计:变更日志 / 合规报告"
      "运维监控:延迟 / 错误率 / 元组数量"
      "文档培训:新人上手成本"
      "持续维护:Bug / 安全补丁 / 升级"
    机会成本(最容易被忽略)
      "这些工程师本可以做什么业务功能?"

7.3 我的决策框架

flowchart TB
    Q{"只需要角色级控制?"}
    Q -->|是| RBAC["用 RBAC<br/>(框架自带)"]
    Q -->|否| Q2{"需要资源级<br/>细粒度控制?"}
    Q2 -->|否| ACL["用 RBAC + ACL<br/>(Casbin / OPA)"]
    Q2 -->|是| Q3{"团队 > 50 人?<br/>有 SRE 支持?"}
    Q3 -->|是| Full["用 OpenFGA 或 SpiceDB<br/>全面部署"]
    Q3 -->|否| Small["用 OpenFGA<br/>但从小处开始<br/>先 PoC 再扩展"]

什么时候该自研?

老实说,只有极少数情况:

  1. 超大规模:日均 Check 请求 > 10 亿次,需要深度定制存储和缓存层
  2. 强合规要求:金融/医疗行业,监管要求授权系统必须完全自主可控
  3. 已有成熟基础设施:团队已经有图数据库、分布式缓存等基础设施,且有专门的平台团队维护

除此之外,用开源方案 + 适度定制 几乎总是更好的选择。


八、实战建议

8.1 授权模型设计原则

  1. 从业务场景出发,而非从技术出发。先画出"谁能对什么做什么"的关系图,再翻译成 DSL。
  2. 控制继承深度。超过 4 层的继承会显著影响性能,也会让模型难以理解。
  3. 显式优于隐式。宁可多写几行 DSL,也不要依赖隐含的权限推导。
  4. 测试先行。OpenFGA CLI 支持模型测试,把测试用例写在模型旁边:
# model_test.yaml
- name: "folder editor can edit documents in folder"
  tuples:
    - user: "user:alice"
      relation: "editor"
      object: "folder:engineering"
    - user: "folder:engineering"
      relation: "parent"
      object: "document:readme"
  checks:
    - user: "user:alice"
      relation: "editor"
      object: "document:readme"
      assertion: true
    - user: "user:bob"
      relation: "editor"
      object: "document:readme"
      assertion: false

8.2 监控指标

上线后必须监控的指标(括号内为健康时的参考值):

指标 参考值 指标 参考值
Check() P50 延迟 3ms Check() P99 延迟 45ms
Check() 错误率 0.01% Write() 吞吐量 1.2K/s
关系元组总数 2.3M 降级触发次数 0

8.3 常见陷阱

  1. 不要把 OpenFGA 当数据库用。它是授权引擎,不是通用存储。不要把业务数据塞进元组。
  2. 不要忽略元组清理。用户离职、资源删除后,相关元组要及时清理,否则会有"幽灵权限"。
  3. 不要在热路径上做 ListObjects。ListObjects 比 Check 慢得多,适合用在"展示用户能看到的资源列表"场景,不适合用在每次请求的权限校验中。
  4. 不要跳过影子模式。直接切换到新系统,出了问题就是线上事故。影子模式是你的安全网。

九、总结

维度 建议
模型选择 RBAC 做粗粒度(API 级),ReBAC 做细粒度(资源级),混合使用
方案选择 优先 OpenFGA/SpiceDB 等开源方案,除非有超大规模或强合规需求才考虑自研
落地路径 PoC → 影子模式 → 逐步切换 → 全面迁移,不要一步到位
数据同步 事件驱动 + 幂等写入 + 定期校验
风险控制 降级策略 + 监控告警 + 模型版本管理 + 回滚机制

授权系统是那种"做对了没人注意,做错了全公司都知道"的基础设施。选择合适的工具、渐进式落地、持续监控——这三件事做好,就能让这栋楼里的每一把锁都锁得住。

一句话总结:RBAC 是标准间的门卡,OpenFGA 是整栋楼的智能门禁——不是替代,是升级。从小处开始,用影子模式验证,让数据说话。


参考资料


思维导图

@startmindmap
<style>
mindmapDiagram {
  node { BackgroundColor #FAFAFA }
  :depth(0) { BackgroundColor #FFD700 }
  :depth(1) { BackgroundColor #E3F2FD }
  :depth(2) { BackgroundColor #F5F5F5 }
}
</style>
title 从 RBAC 到 OpenFGA
* 授权体系
** RBAC
*** 用户→角色→权限
*** 优势:简单、标准、审计友好
*** 痛点
**** 角色爆炸
**** 无法表达资源关系
**** 动态共享难建模
** Zanzibar / ReBAC
*** 一切权限都是关系
*** Subject ─relation─▶ Object
*** 关系图遍历推导权限
** OpenFGA 架构
*** API Layer (HTTP/gRPC)
*** Query Engine (图遍历)
*** Storage (PG/MySQL/SQLite)
*** 6 个核心 API
**** Check / ListObjects / ListUsers
**** Write / WriteModel / Expand
** 落地路径
*** Phase 1: PoC (2-4周)
*** Phase 2: 影子模式 (4-8周)
*** Phase 3: 逐步切换 (8-16周)
*** Phase 4: 全面迁移
** 数据同步
*** 同步写入(强一致)
*** 事件驱动(最终一致,推荐)
*** 定时全量(弱一致)
** 风险控制
*** 服务不可用 → 降级策略
*** 数据不一致 → 补偿任务
*** 模型变更 → 版本管理
*** 性能退化 → 监控告警
** 开源 vs 自研
*** OpenFGA: Okta 背书, SDK 丰富
*** SpiceDB: 全球分布式
*** 自研:仅超大规模/强合规
*** 决策:用开源 + 适度定制
@endmindmap

本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。