对象存储导出

每个达成的目标生成一个 JSON 对象,存入您自己的存储桶。这是通向 BigQuery 之外各类数据仓库的路径。

1. 弥补的缺口

此前,从 MousePlayer 导入数据仓库只有一条路径,通向 Google。如果使用 Snowflake、Redshift 或 ClickHouse,就没有可用路径,尽管三者都能顺利读取对象存储。

因此,桥接写入对象存储,而非逐一对接每个仓库。Snowflake 从 S3 接入,Redshift 从 S3 接入,ClickHouse 从 S3 接入,BigQuery 从 Google Cloud Storage 接入。一次导出即可触达全部仓库。

目标寻址方式
Amazon S3Signature Version 4,主机中包含存储桶
Cloudflare R2针对账户端点使用 Signature Version 4
Google Cloud Storage通过其兼容 S3 的 API,使用 HMAC 密钥
MinIO、Wasabi、Backblaze B2 等针对您的端点使用 Signature Version 4
Azure Blob Storage容器 SAS 链接,我们这边完全无需签名

2. 为什么 Azure 不同,而这反而更好

Azure Blob 不使用 Signature Version 4,而使用 SharedKey 签名。我们本可以再构建一套签名机制,但桥接改为接受 容器 SAS 链接 ,即您在自己的存储账户中生成、已经包含签名的 URL。

这样我们所需的代码更少,您需要给予的信任也更少。我们完全看不到账户密钥;您交付的是自行限定范围的权限,仅针对一个容器,使用自行选择的到期日,且可随时撤销而不影响其他内容。

S3 端也应采取同样克制的做法:仅授予访问密钥写入 这一个前缀 的权限。只能向 mouseplayer/goals/ 追加的密钥,即使泄漏也无法读取其他存储桶。

3. 每个目标一个对象,键以日期组织

对象存储没有追加操作。若使用每日文件,每次都需整体重写;两个目标同时到达还会相互覆盖。因此,每个达成的目标都成为独立对象。

代价是大量小对象;键的组织方式使其可行:

prefix/YYYY/MM/DD/channel/session-goal.json

仓库将一天作为一个分区读取,回填则扫描前缀,而非执行查询。如果希望按项目而非日期分区,可将渠道 ID 放入前缀。

每个对象是一行 JSON

刻意不缩进,因此整个前缀可作为 NDJSON 读取,无需逐个打开对象。内容包括时间戳、项目、会话、客户 ID、目标、价值、货币和回放录制的链接。

空值是 null,而非零

没有金额的目标会写入 null。在仓库中,零会计入一个从未存在的总额;“未约定金额”与“金额为零”的区别会在导出后保留。

4. 返回 403 时,请先阅读此处

S3 请求被拒绝时几乎不给出信息,而日志中的错误消息比 S3 说明更多是有原因的: 地区会参与签名。地区错误与密钥错误都会产生同样的 403,因此直觉上怀疑密钥,只有一半时候正确。

请按此顺序检查三项:

  • 地区,必须与存储桶报告的完全一致。R2 与 Google Cloud Storage 接受 auto 且不校验,其他提供商都会校验。
  • 前缀权限。 权限限定于 mouseplayer/ 的密钥无法写入 mouseplayer-goals/ ,资源 ARN 中末尾的斜线很重要。
  • 端点,针对 R2 与兼容 S3 的存储。粘贴主机名,不含 https://;无论如何我们都会移除此部分,但其后若附加路径,便指向不同的存储桶。

访问密钥 ID 刻意以明文存储。按设计,它会随每个签名请求传输,因此加密只是徒增工作,并无保护作用。密钥的秘密部分会加密,保存后不再显示,也绝不进入承载任务的内部队列。

此处提及的所有商标均属于各自所有者。MousePlayer 与这些提供商不存在商业关系。