对象存储导出
每个达成的目标生成一个 JSON 对象,存入您自己的存储桶。这是通向 BigQuery 之外各类数据仓库的路径。
1. 弥补的缺口
此前,从 MousePlayer 导入数据仓库只有一条路径,通向 Google。如果使用 Snowflake、Redshift 或 ClickHouse,就没有可用路径,尽管三者都能顺利读取对象存储。
因此,桥接写入对象存储,而非逐一对接每个仓库。Snowflake 从 S3 接入,Redshift 从 S3 接入,ClickHouse 从 S3 接入,BigQuery 从 Google Cloud Storage 接入。一次导出即可触达全部仓库。
| 目标 | 寻址方式 |
|---|---|
| Amazon S3 | Signature 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 与这些提供商不存在商业关系。