跳到正文

ESA Pages 体验之旅(4):小项目的存储选型

ESA Pages 体验之旅 · 1 · 2 · 3 · 第 4 篇(当前) · 5 · 6 · 7 · 8 · 9

应用需要跨设备保存业务记录,也需要在多个边缘节点间共享验证码、会话和限额。函数内存会随执行环境释放,缓存也允许淘汰,这些数据需要独立的持久存储。

本项目选择香港地域的 TableStore 容量型实例,按完整主键访问,使用条件更新控制并发,低用量时按量付费。数据库接口满足了当前需要,Node SDK 接入 ESA 的兼容成本则要另外评估。

需要持久化的数据

业务记录需要长期保存;验证码、会话和限额除了有效期,还要处理并发访问。不同数据对存储的要求如下。

可重建缓存、持久业务记录和认证状态,需要不同的持久性与并发保证

数据要求 选型时要确认的能力
可重建的短期响应 允许淘汰,有 TTL,未命中时可以重新计算
长期业务记录 持久保存、按用户隔离、分页读取、备份恢复
只能成功一次的状态 条件创建或更新、冲突检测、原子消费
多个节点共用的配额 共享计数、原子操作和明确的失败处理

这些记录都能写成 JSON,语义却不同。把文件保存下来,只解决了持久化的一部分;并发请求是否覆盖、删除后会不会被旧副本重新写回,还取决于存储接口与应用模型。

候选存储服务

方案 适合的用途 本次需要额外解决的部分
ESA Cache API 短期 HTTP 响应复用 缓存可以淘汰,不能承担权威业务数据
ESA KV 低频写、高频读的键值资料与配置 要核对当前写入入口、条件更新和并发消费契约
OSS 对象存储 文件、快照、导出与归档 整份 JSON 并发修改、索引和事务需要另做
托管 MySQL / PostgreSQL 关联查询、事务、成熟 ORM 适配 固定或最低资源费用,驱动与 ESA 网络能力
托管 Supabase PostgreSQL 数据 API、Auth 等组合能力 产品类型、正式规格、网络和各服务费用
TableStore 主键查询、按量读写、条件更新 行模型、索引设计和 Node SDK 适配

选定数据库后,还要核对 HTTP 签名、协议、返回结构和 SDK 依赖。这部分成本不包含在存储服务的价格中。

ESA KV 的一致性与条件写入

当前边缘存储文档说明,写入先到中心,随后清除边缘旧值;新值在边缘未命中时回中心读取,并明确描述为适合要求全局一致性的低频写、高频读业务。

这份文档没有给出固定几十秒的旧值传播时间。首次回中心读取会增加访问延迟,与读取结果是否一致需要分别判断。

本次没有用 ESA KV 承载认证状态,因为所需的条件占用、版本更新和一次性消费接口尚未确认并验证。读一致性只是其中一项要求,这些并发操作仍需单独核对。

Supabase 的托管方式

「Supabase」可能指海外 SaaS、阿里云托管产品或自行部署。阿里云又有不同托管路线,不能共用一份价格或免费规格结论。

以 AnalyticDB 托管 Supabase为例,PostgREST 提供数据 HTTP API,Auth 提供更完整的认证 HTTP API。前者替换数据库传输,后者把认证操作放在另一个服务内部。它们对 ESA 子请求预算的影响很不一样。

Supabase 的 HTTP 接口可以作为 ESA 的接入方向。本项目已有的主键访问适合 TableStore,Supabase 的正式费用、出网和认证配置还需验收,因此暂未迁移。具体调用次数与认证流程见认证选型实验。

TableStore 的条件操作

TableStore 是托管的表格存储,支持按主键访问、条件操作及批量读写。应用不维护数据库进程,也不需要为了少量数据长期预留一台服务器。

实际接口验证过两类并发条件:16 个请求尝试「键不存在时创建」,只有一个成功;16 个请求读同一快照后按版本条件删除,也只有一个成功。后者由读取和条件删除组成,每个参与者仍需要两次访问。

这给一次性消费提供了可用原语,但不是完整认证框架适配器。唯一身份、索引恢复和多记录状态仍需应用组织。BatchGetRow、BatchWriteRow 可以减少网络往返,批写却允许逐行失败,不能当作跨记录事务。局部事务另有表与分区约束,并增加开始、提交等调用。

SQL DML支持非事务表的 INSERT、UPDATE、DELETE,其中 UPDATE / DELETE 要求完整主键等值条件,通用 UNIQUE、FOREIGN KEY 等约束也不受支持。需要复杂关系和通用认证适配器时,关系数据库仍值得重新比较。

容量型实例的费用

容量型实例按量使用。控制台显示的预留吞吐量为 0,表示没有预留容量,实际读写仍会计费。CU 模式计费至少要区分存储、读 CU、写 CU 和公网下行;额外索引等功能再加对应费用。

月费用 = 存储 GB·小时 × 存储单价
       + 读 CU / 10000 × 每万读 CU 单价
       + 写 CU / 10000 × 每万写 CU 单价
       + 公网下行 GB × 下行单价
       + 额外功能费用

例如一个月 30 万读 CU、10 万写 CU,代入官方容量型计费示例中的 0.004 元/万读 CU 和 0.002 元/万写 CU,读写部分是 0.14 元。这只是展示算法,未含存储、网络,也不是香港实例的完整报价;正式预算应取目标地域当期单价。官方容量型计费示例

一次 API 也不等于一个 CU。批请求中的行数、记录大小都会影响容量消耗。函数分布在边缘,数据库位于固定地域,不能因为都属于阿里云就默认走免费内网。

TableStore 的适用范围

这次选型的有效范围是少量、明确的主键操作,以及能由条件写入表达的并发约束。以后若需要复杂关联、更多事务或成熟 ORM,应该重新比较,不必围绕第一版选择持续改写所有需求。

TableStore 的条件接口满足了当前的持久化需要。接入 SDK 时又遇到了变量声明错误和 Node API 兼容问题,它们分别需要修复依赖源码、验证 ESA 的执行环境,属于数据库选型之外的接入成本。