ESA Pages 体验之旅(4):小项目的存储选型
应用需要跨设备保存业务记录,也需要在多个边缘节点间共享验证码、会话和限额。函数内存会随执行环境释放,缓存也允许淘汰,这些数据需要独立的持久存储。
本项目选择香港地域的 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 的执行环境,属于数据库选型之外的接入成本。