Cloudflare D1
SQLite
Serverless
Banco de Dados
Edge

Cloudflare D1:边缘的 SQLite 数据库 — 以及为什么“边缘”的含义并不像看上去的那样

D1 并不在所有 Cloudflare 数据中心运行其查询 - 它有一个发生所有写入的主区域,以及具有最终一致性的读取副本。

Cloudflare D1:边缘的 SQLite 数据库 — 以及为什么“边缘”的含义并不像看上去的那样

将 D1 称为“[边缘数据库 3]”会产生该架构无法完全满足的期望。脑海中的形象是 SQLite 同时在所有 300 个 Cloudflare 数据中心中运行,其查询从地理位置上最接近用户的点进行响应。现实情况更受限制:有一个主要区域,所有写入都发生在其中,并且读取副本遍布整个网络,接收这些写入的延迟最多为 60 秒。如果您的主要银行位于北美,并且您从在圣保罗运行的 Worker 进行写入,则该写入在被确认之前需要 80 到 150 毫秒的往返时间。快速入门没有提到这一点。

D1的真实架构

D1 使用 SQLite 作为其数据库引擎——与在浏览器、移动设备和桌面应用程序中运行的 SQLite 相同。在此引擎之上,Cloudflare 构建了一个复制层:主实例接收所有写入并将更改传播到分布在全球网络上的只读副本。

创建 D1 银行时,您选择(或让 Cloudflare 自动选择)您的主要区域。这个选择决定了作品的落地地点。在圣保罗运行的 Worker 进行的读取可以由附近的副本提供服务,但 Worker 的执行时间会有 5 到 20 毫秒的额外延迟。同一工作人员进行的写入会发送到主要区域 - 如果该区域是 us-east-1,则在您收到确认之前,仅网络往返就需要 80 到 150 毫秒。

副本传播时间与生产相关:对主数据库的写入最多可能需要 60 秒才能出现在所有副本上。在此间隔期间,从过时副本读取的工作线程会看到预写数据。这种行为称为最终一致性——副本将收敛到正确的状态,但不会立即收敛。

生产中你会遇到的一致性问题

破坏最终一致性的模式是先写后读。您创建一个用户,重定向到配置文件页面,加载配置文件的查询会命中尚未收到 INSERT 的副本。结果是一个空的配置文件,或者一个 404 错误,或者用户看到但不理解的不一致状态。

这个问题存在于任何具有复制功能的数据库中,但对于 D1,它会在没有警告的情况下出现,因为绑定抽象隐藏了正在查询的副本。 Cloudflare 正是针对这种情况创建了 Sessions API:在同一个 D1 会话中,写入保证后续读取将看到写入的数据,无论哪个副本提供查询服务。

Sessions API 的工作原理是使用 0 创建会话。在回调中,所有查询共享会话上下文,并且 D1 确保写入后读取返回更新的数据。对于结合写入和立​​即读取的流程(帐户创建、设置更新、订单完成),使用 Sessions API 是避免用户可见的不一致的直接途径。

对于纯粹的只读流,例如列表和仪表板,最终一致性不是问题:数据可以延迟几秒钟,而不会产生任何明显的影响。

真实价格:当免费套餐不再足够时

D1 的免费套餐提供 5GB 存储空间、每天读取 500 万行、每天写入 10 万行。这些数字抽象起来听起来很慷慨,但 D1 的读取成本并不基于返回的行,而是基于数据库引擎检查的行。

扫描 10 万行以返回 5,000 行的查询会消耗 10 万个读数,而不是 5,000 个读数。一个拥有 1000 名活跃用户的应用程序在没有足够索引的情况下进行列表查询可能会在几个小时内耗尽 500 万个每日读数。免费层足以用于开发、小容量内部工具和原型设计,但不适用于具有真实用户流量的应用程序。

当免费套餐不够时,下一步需要 Workers Paid 计划(平台每月 5 美元)加上 D1 的可变成本:每百万行读取 0.001 美元,每百万行写入 1 美元,每月每 GB 存储 0.75 美元。写入成本有一个简单的算术:每个用户插入 10 行的注册流程相当于每百万注册用户的写入成本为 10 美元。对于快速增长的应用程序,这个数字出现得早于预期。

读取的成本几乎完全取决于索引的质量。使用合适的索引,返回 20 行的查询将读取 20 行。如果没有索引,相同的查询可以读取 50 万行,成本增加 500 倍。

创建银行前如何规划主要区域

D1主要区域是银行创建过程中不可逆转的决定。以后无法移动主数据库 - 替代方法是导出数据,在所需区域创建新数据库并导入。这使得区域选择成为在编写第一行代码之前需要仔细考虑的少数基础设施决策之一。

经验法则:主要区域应该是大多数写作的起源地。对于拥有巴西用户的巴西产品,Worker 可能在圣保罗 PoP (GRU) 或类似设备上运行。 Cloudflare 提供 1 作为 D1 主要区域选项 - 为巴西产品选择该区域可将写入延迟从 80-150 毫秒减少到 5-20 毫秒。

要检查哪个区域最有意义,请使用带有前后时间戳的简单 2 来测量候选区域的 Worker 网络延迟。主区域选择错误的成本不会出现在开发中,而是出现在应用程序投入生产且每次写入给用户带来 100 毫秒的明显延迟时。

付费套餐中每家 2GB 和 10 家银行的限制也包含在初步规划中。如果应用程序往往会增长到超过 2GB,则需要在第一个数据到达之前考虑多个 D1 存储体之间的数据分区——稍后使用生产中的数据重构此分区,工作量要大得多。

另请阅读

  • [Cloudflare KV:当您需要编写时,全球分布式意味着什么4
  • [生产中的 D1:性能、限制以及无法单独扩展的因素5
  • [D1 中的迁移:如何对模式进行版本控制以及出错时会发生什么6
  • [Cloudflare Durable Objects:边缘的一致状态 - 真正改变的是什么77
  • [生产中的 Cloudflare Workers:hello world 之后发生了什么变化8
  • [Cloudflare Workers 与 Pages:选择之前最重要的区别9