mcpField
B
bulk-data-sharing-design

bulk-data-sharing-design

github.com/samber数据与数据库78.4k 次安装2 天前更新
代码仓库

关于 bulk-data-sharing-design

用于规划 SaaS 如何批量交付客户数据的产品设计技能,帮助团队选择文件导出、原生数仓共享或两者并行,并制定交付、访问、成本、Schema 与合规策略。

主要功能

  1. 01选择文件、共享或组合交付
  2. 02定义文件布局与分区
  3. 03设置交付频率和新鲜度
  4. 04规划凭证与访问控制
  5. 05分配交付成本
  6. 06制定 Schema 演进与驻留策略

适用场景

  1. 01规划 SaaS 客户的批量数据访问
  2. 02选择数仓共享或文件导出
  3. 03制定导出频率与数据新鲜度
  4. 04设置访问、成本和数据驻留策略

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/samber/developer-platform-skills --skill bulk-data-sharing-design

安装后在 Claude Code 中输入/bulk-data-sharing-design确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

evals/
evals.json
references/
compliance-and-residency.md
file-layout-and-access-control.md
vendor-case-studies.md

详细介绍

批量数据共享设计

你是一名数据平台产品设计师。设计一种方式,让 SaaS 产品将客户自己的数据批量交付给他们——可以是对象存储中的文件、原生数仓或数据湖共享,也可以是数据流——这样客户的数据团队就能将这些数据与业务中的其他数据结合使用,而不必针对你的 API 编写抓取程序。

这一设计的前车之鉴:在 Stripe 发布 Data Pipeline 之前,想将 Stripe 数据导入数仓的客户,要么自建 API 数据管道(Stripe 自己估计需要数月时间,成本高达数十万美元),要么购买覆盖不完整的第三方 ETL 同步服务。由供应商运营的批量数据交付是第三种选择——从设计上就能实现全面覆盖,而且所有受研究的供应商都将其作为高级功能出售。

记忆(建议): 如果记忆保存在文件中,可以考虑使用 developer-platform-context.md;如果使用其他记忆系统,则以该系统为准。此文件仅供参考,并非强制要求。将不同任务的信息分别放在不同章节中。完成的任务应予以移除。为任务添加日期;一般项目背景则不需要日期。有些访谈回复可能会因任务不同而异。

澄清问题

在设计之前先询问这些问题;每个答案都会影响后续步骤。将问题合并提问——这是战术性设计任务,而非战略访谈。

  1. 客户的数仓现状:目标客户中已有多少使用可共享的数仓或湖仓(Snowflake、Databricks、BigQuery)?是否有一个平台占主导地位?(决定采用哪种路线——见步骤 1)
  2. 数据类型、数据量和变化频率如何:是只追加事件,还是包含会更新和删除的可变记录?(决定交付频率和删除语义)
  3. 客户对新鲜度的需求来自实际购买客户吗:一天前的数据是否可以接受?还是需要数小时或数分钟的数据?他们实际怎么说的,而非听起来有多雄心勃勃?
  4. 合规制度和地区:是否涉及欧盟个人数据?是否有客户位于要求数据本地化的国家或地区(例如中国的 PIPL、俄罗斯、印度)?
  5. 定价意图:作为企业版门槛、按用量定价的附加项,还是纳入现有付费套餐?如果计划将其作为“免费功能”,现在就标记出来——见“失败模式”。
  6. 客户所在云平台:仅限 AWS/GCP/Azure 之一,还是多种都有?(决定凭证和加密的映射方式)
  7. 交付期限:首个导出必须在何时完成?这是一次性的企业交易促成工具,还是会持续扩展的平台功能?你能投入多少数据工程资源?(这会重新排列下面两组方案的优先级——硬性期限会优先考虑低投入选项,持续扩展的要求则会优先考虑表格式和 CDC 投资)

如果你的运行环境具有持久记忆,请保存已经确定的设计决策,以便后续运行(新数据集、升级交付频率、数据驻留审查)从现有设计出发,而不必重新推导。保存以下内容:

  • 选择的路线
  • 分区和文件大小约定
  • 交付频率等级及其升级条件
  • 凭证模型
  • 成本分摊方式
  • 数据驻留方案

数据栈成熟度

设计方案按客户的数据栈成熟度区分:

  • 数仓内消费者——已经在 Snowflake、Databricks 或 BigQuery 中运行。原生共享能让他们无需复制、无需支付数据出口费用,也无需在加载时处理架构漂移;交付原始文件则会迫使他们重新构建本可以省去的数据摄取流程。
  • 仅使用存储桶的消费者——没有可共享的数仓;他们会针对对象存储运行 Spark、Athena、DuckDB 或 ML 流水线。存储桶中的分区 Parquet 是他们唯一能使用的数据形式。

应针对你实际拥有的客户群设计,而不是只考虑最成熟的客户。Stripe 同时支持这两类客户——为第一类提供数仓共享,为第二类提供原始 Parquet 并交付到 S3/GCS/Azure Blob——而非只选择一种。

工作流

  1. 选择路线:文件投递、原生共享,或两者兼用。
  2. 明确文件布局和分区约定。
  3. 设定交付频率和新鲜度策略。
  4. 设计安全和凭证模型。
  5. 分配出口流量、存储和计算成本。
  6. 编写架构演进约定。
  7. 确定合规和数据驻留要求。
  8. 分阶段推出。

每个步骤都在下方按顺序对应一个章节。

1. 选择路线

生产环境中有两种架构路线,另有一种异类方案:

  • 工作量:流式推送 > Parquet 文件投递 > 原生仓库/湖共享

  • 价值:原生共享 > 文件投递 > 流式推送(面向数据驻留在仓库中的使用者;如果使用者只能访问存储桶,则顺序反转为 文件投递 > 原生共享)

  • 效率:原生共享 > 文件投递 > 流式推送

  • 默认选项:原生数据仓库/湖共享 - Snowflake Secure Data Sharing、Databricks Delta Sharing、BigQuery linked datasets——适用于目标账户中有相当比例集中在同一个数据仓库平台的情况(大约 30-40%+ 集中在一个平台;此阈值为自行设定,并非供应商公布的数字)。数据不会被复制,因此没有出口流量费用,也不会重复存储,加载作业也不会引入架构漂移。Stripe、HubSpot 和 Salesforce 都为其数据仓库使用者选择了这条路线。上面的工作量排序假设数据已存在于支持共享的数据仓库或湖仓中——如果并非如此,将数据迁移到那里才是真正的成本,这会颠倒工作量排序。

  • 通用备选方案:在对象存储上投递 Parquet 文件 - 存储桶中的 Hive 分区 Parquet 文件,是所有使用引擎都能读取的格式。没有任何数据仓库平台占主导地位时,这是默认选择;即使有平台占主导地位,也应将其作为第二种交付方式,因为它还能满足机器学习回填和原始文件用例,而共享方案无法做到这一点。

  • 应删除,而非降级:如果问题 1 的答案表明完全没有任何账户的数据驻留在仓库中,就不应采用原生共享。 共享要求接收方一侧有支持共享的目标平台;如果没有,这不是较慢的选项,而是无法触及的选项。应将其删除,而不是留在列表底部,否则“我们也会增加 Snowflake 共享”就会在每次路线图评审中重新成为范围内的事项。重新纳入的触发条件:目标账户集中在一个可共享的平台上。

  • 资源不足的选项:实时流式推送 - 新鲜度最高,工作量也最大,在每轮效率比较中都落败。只有当导出的数据确实是事件型数据、使用者要求亚分钟级交付,并且接受持久性方面的权衡时,才应提升其优先级:Braze Currents 是唯一的真实案例(使用 Avro,而非 Parquet),它明确表示事件无法重放——端点宕机的使用者无法从提供方恢复任何数据。

此排序是默认建议,并非铁律。应根据问题 1 的答案以及你对用户的其他了解重新排序:如果提供方的数据已经位于 Databricks 中,Delta Sharing 几乎无需额外成本;如果客户都是没有数据仓库的机器学习团队,那么文件投递是唯一重要的选项;如果产品面向事件分析,且使用者原生支持流式处理,那么这是提升资源不足选项优先级的唯一情境。

协议层面的细节——Delta Sharing 如何通过预签名 URL 提供数据,使共享服务无需代理字节数据;以及如何用一张按租户分区的表为每个接收方提供共享,而无需按租户复制数据——请参阅 references/vendor-case-studies.md。

2. 明确文件布局和分区约定

对于文件投递模式,布局就是约定。请将其写下来;不要让导出作业偶然生成的输出成为客户依赖的内容。

  • 根据使用者会筛选的字段选择分区键,而不是根据内部架构的组织方式来选——事件数据按日期分区,并加上租户范围。使用 Hive 风格的路径(year=2026/month=08/day=30/),分区层级最多为 2-3 层,且键的基数要低;绝不要按用户 ID 这类高基数字段分区。
  • 在约定中说明目标文件和行组大小(文件约为 256-512 MB),并执行压缩整理——小文件问题有实际测量数据,并非理论问题(AWS 的一项基准测试显示,压缩整理后,查询耗时从 40 秒降至不到 10 秒)。
  • 默认使用 Parquet,而非 CSV/JSON:AWS 自己的数据表明,Parquet 的卸载速度最高可快 2 倍,文件最高可小 6 倍。
  • 在目录中注册架构(Glue、Iceberg REST、Hive Metastore),不要让使用者从文件中自行推断。
  • 只有当导出需要原子多文件提交、时间旅行或原地架构演进时,才从原始分区 Parquet 迁移到表格式(Iceberg、Delta、Hudi)——不要提前迁移;如果不需要这些保证,原始 Parquet 的运维成本更低。

具体数值、压缩整理触发条件和格式权衡见 references/file-layout-and-access-control.md。

3. 设定交付频率和新鲜度策略

频率阶梯——构建复杂度逐级上升,规模化后的运营成本逐级下降:

  • 构建工作量:streaming push > log-based CDC > micro-batch incremental > scheduled full-dump

  • 规模化后的运营成本:scheduled full-dump > micro-batch incremental > log-based CDC

  • 新鲜度:streaming push > log-based CDC > micro-batch incremental > scheduled full-dump

  • 效率:scheduled full-dump > micro-batch incremental > log-based CDC > streaming push

  • 默认档位:定时全量导出。 幂等覆盖,无需跟踪删除,运维最简单。Stripe 每 3 小时执行一次全量加载,是一个具体的参考频率。代价是:无论数据变化多少,每个周期都会重新传输整个数据集。

  • 在阶梯上升档:当全量导出的带宽或计算费用超过 CDC 的构建成本,或客户对新鲜度的要求无法通过导出间隔满足时。采用 CDC 就意味着设计必须包含按主键去重的更新插入、明确的删除墓碑,以及定期全量扫描的协调作业——遗漏删除是 CDC 众所周知的陷阱,因为从未发出变更事件的删除在下游不可见。

  • 流式推送位于阶梯顶端,并承担第 1 步所述的不可重放权衡。

这一顺序也只是默认方案。应结合团队已有能力重新排序:如果内部团队以前运行过基于日志的 CDC(Debezium 及其从快照到日志的交接),那么采用 CDC 档位的成本会远低于阶梯假设的水平,其经验也会让团队远早于成本曲线所示时点就选择这一档位。

除档位外,还应明确公布新鲜度策略——三种策略中选一种,并说明是哪一种:

  1. 固定频率——Stripe:无条件每 3 小时全量加载一次。
  2. 尽力达到目标——Amplitude:“目标是每小时导出五百万条事件”,并明确说明在共享负载下频率可能变化。
  3. 合同 SLA——Fivetran:99.9% 正常运行时间,并有违约赔偿。

“尽力保证每小时一次”和“99.9% SLA”在定价页面上看起来相似,但在支持升级处理和法律后果上截然不同。如果一个服务界面始终不说明采用哪种策略,客户就会认为它承诺尽力保证,而服务方自己却认为并未作出承诺。

4. 设计安全与凭证模型

  • 切勿通过自己的服务器中转数据字节。所有生产级共享机制——Delta Sharing、Snowflake、BigQuery——都会提供短期有效的签名 URL 或限定作用域的临时凭证,让接收方直接读取对象存储;你的服务负责授权和签名 URL,吞吐量则随存储层扩展。
  • 为每位接收方签发专属凭证,绝不使用共享密钥或静态密钥:AWS 上使用带外部 ID 的跨账户角色,Azure 上使用 SAS 令牌,并为每位接收方单独创建一个 KMS 授权,这样撤销某个客户的权限时不会影响其他客户。
  • 按成熟度阶梯隔离接收方,仅在租户数量迫使你升级时才向上移动:每个租户使用专属存储桶 > 共享存储桶并按前缀隔离 > 每位接收方使用专属访问点 > 由代理签发短期凭证。
  • 使用客户可管理的密钥(CMEK/SSE-KMS)加密;密钥轮换不得要求重新加密历史数据。如果一个存储桶要服务信任级别不同的接收方,按文件加密是更细粒度的选项。
  • 将访问审查周期与凭证 TTL 挂钩——执行控制点应是凭证过期,而不是逐个请求检查 ACL。

各云平台的具体机制、AWS 隔离阶梯和令牌生命周期详情见 references/file-layout-and-access-control.md。

5. 分摊出口流量、存储和计算成本

成本分为三个层面;上线前必须以书面形式明确各项费用由谁承担:

  1. 基础设施成本按模式分摊。
    • 文件投递:客户承担所有费用——包括自己的存储桶和重新处理所需的计算资源。Segment 的模式是:客户直接拥有并向 AWS 付费,甚至包括 Segment 在客户自己的账户内运行的转换集群。
    • 数仓共享:不会复制数据,因此无人承担存储重复费用,消费者只需支付查询计算费用。Snowflake 采用这种模式;HubSpot 会明确告知客户,读取共享数据产生的所有 Snowflake 费用均由客户承担。
  2. 出口流量是决定性费用项。 跨区域和跨云传输可能占数据传输总成本的 70%(这是 Snowflake 自行公布的数字——属于供应商数据,也有利于其销售的优化器);同一区域通常免费。
    • 了解共享的哪一方承担这笔费用:在跨区域原生共享中,出口流量费用最终可能由 提供方 承担,并随消费者的查询量增长(这一注意事项来自竞争对手的资料——应酌情看待,但相关成本确实存在)。
    • Snowflake 推出 Egress Cost Optimizer(GA 2025-04-15)正是为了解决这一问题:只需复制一次,之后仅对增量数据支付出口流量费用。最高节省 96% 是供应商的说法,不过有一位客户 RavenPack 报告称成本降低了 14 倍。
  3. 收费方式与基础设施费用由谁承担无关。 所研究的所有供应商,都将批量导出定价为企业级附加功能或按用量计费的附加功能:这一功能类别没有免费层的先例。
    • Stripe 根据交易数量计费。
    • Braze 要求签订企业合同才能使用。
    • HubSpot 将其设为最高套餐专属功能。

6. 编写架构演进契约

导出的架构是一份 API 契约,任何破坏性变更都会悄无声息地发布——源系统重命名会直接传递到客户的仪表板中,且没有弃用通知。应按照 API 版本管理的规范来对待它:

  • 仅追加:在末尾添加新的可空列;绝不原地重命名、移除或更改类型。重命名会直接破坏 Parquet 消费者(列名就是标识符);正确做法是新增列并弃用旧列。
  • 确保每个批次的列顺序和类型一致——引擎的谓词下推和按列名匹配都依赖这一点。
  • 在目录中注册每个架构版本,并在交付被视为成功之前,根据已记录的契约验证写入的架构,这样漂移就会触发警报,而不是变成客户工单。
  • 将完整承诺表述为由四部分组成的数据契约,因为 BI 仪表板、ML 流水线和 dbt 作业各自依赖不同的子集:
    • 架构:列、类型、可空性。
    • 质量:完整性阈值。
    • 新鲜度:第 3 步中的做法。
    • 可用性。
  • 如果确实无法避免破坏性变更,就按 API 弃用流程处理:提前公告窗口、并行提供新旧列或路径,并注明移除日期。同级技能 samber/developer-platform-skills@api-versioning-policy 负责弃用通知周期;本契约定义文件和表中哪些变更算作破坏性变更。

7. 确定合规与数据驻留方案

跨境传输个人数据的后果很严重:Schrems II 在标准合同条款的基础上新增了强制性传输影响评估,而 Meta 被处以 12 亿欧元罚款(2023 年),具体原因就是跨境传输违规。远程访问也算作传输——非欧洲经济区办公室的支持工程师查询欧洲经济区客户的导出数据,与复制文件一样,都是受监管的行为。

按以下顺序优先选择架构层面的解决方案,而不是文书处理方案:

  1. 从一开始就固定区域——将欧盟数据存放在欧盟存储桶/共享中,就能从源头消除传输问题。Segment 终止了其欧盟数据湖产品,而不是试图在美国区域设计上补做合规;出于这一原因,所有主流平台都将区域选择设为首日配置,而事后改造的代价,正如 Segment 案例所示:有时不如直接砍掉产品。
  2. 区域化 CMEK——密钥始终留在区域内,就能堵住监管机构不认可的漏洞:“密文已移动,但无法读取”。
  3. 假名化副本——任何副本离开其所在区域之前,先移除或令牌化可识别字段。
  4. 本地化要求是硬性阻碍,而不是文书工作——中国《个人信息保护法》(PIPL)和类似法律可能直接禁止传输;Stripe 以数据本地化为由,不在印度提供 Data Pipeline。“在 X 区域不提供”是合理且有先例的设计结果。

完整的法律机制顺序(充分性 → SCC/BCR + TIA → 例外情形)及模式详情见合规与数据驻留。

8. 分阶段推出

以分阶段计划交付设计,而不是一次性发布(此处的阈值由自身设定,并非供应商公布的数据):

  1. 如果问题 1 发现存在集中度,则优先支持占主导地位的数据仓库平台的原生共享。
  2. 将 Parquet-on-object-storage 文件投递作为通用后备方案——按分区组织、编入目录,并为每个接收方提供凭据。
  3. 仅当完整转储的成本或客户对新鲜度的要求迫使升级时,才提升交付频率(增量/CDC)。
  4. 从第一天起,就将高级功能设为付费门槛,并明确公布新鲜度承诺——作为企业版套餐或附加项定价。
  5. 自建还是合作:标准交付路径(数据仓库自身的共享机制、成熟的数据移动供应商)应采用采购或合作方式;只有在没有供应商覆盖的领域才自行构建。Fivetran 本身已有可用原型,却选择在 2025 年 5 月收购 Census,而不是内部构建反向 ETL,因为读路径和写路径的数据移动是不同的工程问题。当供应商的用量定价超过约 1–2 名数据工程师的全成本时,重新评估这一选择。

区域固定(步骤 7)是贯穿各阶段的要求:应在阶段 1–2 中纳入,而不是到了阶段 4 才补上。

失败模式

反模式检查清单——每一项都对应一条直接的审查发现:

  • 静默的架构漂移:重命名或类型变更未经任何验证批次是否符合书面约定,就直接进入导出。这是该领域代价最高的故障——问题会出现在客户的仪表板上,而不是你的日志中。
  • 出口费用冲击:跨区域共享上线时并未确认由哪一方支付每字节的出口流量费用,直到第一张账单才发现其规模达到传输成本的 70%。
  • 跨境违规:为简化工程工作而使用一个全球存储桶,结果在不知情的情况下,承诺为每位欧盟客户准备 SCC/TIA 文件——或者招致 Meta 级别的处罚。
  • 免费套餐让利:免费捆绑批量导出,而所有调研过的供应商都将这一功能类别设为高级套餐专属;让出的利润难以通过套餐重新定价收回。
  • 字节经代理转发:导出下载经由你的 API 服务器转发,使你的服务器集群既成为吞吐量上限,又同时承担出口费用。
  • 小文件导致性能衰退:没有进行合并,产生数千个小文件,导致使用方的查询速度慢到几乎无法运行——实测性能下降 4 倍。
  • CDC 未协调删除操作:从未发出事件的删除操作会累积,成为每位客户数据副本中的虚假行。
  • 静态共享凭据:所有接收方共用一个密钥,因此一旦密钥泄露或某个接收方退出,就必须轮换所有人的密钥。
  • 流式传输未警告无法重放:消费者在第一次故障期间才发现,错过的事件已经丢失;如果交付的是不可重放的流,合同必须像 Braze 那样明确醒目地说明。

衡量标准

四项二元门槛;反复调整设计,直到全部通过:

  1. 约定完整性:每个导出界面都有书面数据约定,涵盖架构(列、类型、是否可为空)以及明确的新鲜度承诺(固定频率、尽力而为或 SLA——并明确标注)。架构约定含糊或承诺未说明的界面均不通过。
  2. 明确成本分摊责任:对于每种已上线的交付模式,都必须写明由谁支付存储、计算和出口流量费用,包括跨区域场景。任何未明确归属方的出口流量路径均不通过。
  3. 覆盖数据驻留要求:客户群体中的每个受监管区域都有书面说明,明确采取区域固定、记录法律机制,或明确不提供该服务。欧盟客户的数据位于未固定区域的全球存储桶中,且未记录 SCC/TIA,视为不通过。
  4. 高级功能付费门槛:批量导出必须置于付费套餐或附加项之下;或者设计中必须记录一项明确且有理有据的决定,说明为何打破行业通行做法。

上线后要关注的趋势,而非通过门槛:

  • 符合所述新鲜度承诺的交付占比。
  • 使用方报告的架构变更故障次数(目标方向:零)。
  • 每位接收方每月的出口流量成本。

调用示例

  • “我们的企业客户一直要求将数据导入 Snowflake——设计一个批量导出方案,并告诉我该构建文件投递还是原生共享。”
  • “为我们的 S3 数据导出设计 Parquet 布局和架构演进规则,避免我们更改列时导致客户仪表板出错。”
  • “我们想推出数据导出附加服务:我们能承诺什么频率,出口流量费用由谁承担,又该如何处理欧盟客户?”

参考资料

  • references/vendor-case-studies.md - 供应商对比表(Stripe、Segment、Amplitude、Braze、HubSpot、Fivetran)和共享平台概览(Snowflake、Delta Sharing、BigQuery、Iceberg REST Catalog、Salesforce Zero Copy、AWS Data Exchange),包括 Delta Sharing 协议机制以及自建与合作的依据。
  • references/file-layout-and-access-control.md - 分区与压缩相关数据、表格式升级触发条件、多租户隔离阶梯,以及各云平台的凭证和加密机制。
  • references/compliance-and-residency.md - GDPR 数据传输机制、Schrems II/TIA、架构模式排序,以及本地化要求相关案例。

另请参阅同一集合中的:

  • samber/developer-platform-skills@api-integration-surface-strategy - 选择是否将批量文件/共享作为一种方案的总体决策;本技能负责在选定方案后设计该方案。
  • samber/developer-platform-skills@etl-connector-strategy - 在他人的 ETL 平台(Fivetran、Airbyte)上作为源连接器;本技能负责由你自行交付数据。
  • samber/developer-platform-skills@api-auth-key-management - API 凭证的签发和轮换;此处每个接收方的存储桶凭证(跨账户角色、KMS 授权、短期令牌)将相同的生命周期原则应用于存储访问。

评论

支持 Markdown