Cloudflare
KV
Cloudflare KV
Produção
Padrões
Cache
Limites

生产中的 KV:有效的模式和一开始会产生误导的模式

适用于生产环境的 Cloudflare KV 使用模式:元数据技巧、模块级缓存、list() 的索引键以及快速耗尽免费层的反模式。

生产中的 KV:有效的模式和一开始会产生误导的模式

每天一千次写入似乎就足够了,直到您将任何东西投入到真正用户的生产中。将会话令牌写入 KV 以进行 [身份验证11] 的登录系统会在半小时的中等流量下耗尽此限制。第一次与 KV 真正极限的对抗很少发生在舞台上。

免费套餐——每天 100,000 次读取和 1,000 次写入——旨在反映正确的使用模式:大量读取,最少写入。当团队一致使用此模型的 KV 时,免费套餐会持续很长时间。当用作会话库或每用户状态存储时,限制出现在第一周。

有效的模式

KV最扎实的用途是存储重复读取且很少更改的应用程序配置。包含产品标志、业务参数、白名单、第三方端点的 JSON — 此类数据会根据管理操作而不是根据用户进行更改。对 KV 的写入会传播到所有 PoP,并无需相关成本即可服务数百万个请求。如果团队每月写入该密钥十次并读取该密钥一千万次,则可以轻松享受免费套餐。

渲染的 HTML 的缓存遵循相同的原则。博客文章、产品页面、每个用户都不会更改的搜索结果 - 您渲染一次,将其保存在具有适当 TTL 的 KV 中,并直接从 PoP 缓存为任何后续请求提供服务。渲染下降、延迟下降和写入次数的成本与内容更新的频率成正比,而不是与流量成正比。

只要会话是一次性写入的,具有 TTL 的会话令牌也适用。您可以在身份验证时写入令牌(每次登录一次写入),并在每个后续请求时读取它。如果用户登录一次并活跃数小时,则读/写比率非常好。打破这个模型的是具有可变状态的会话:每个会话数据更新都会变成写入,并且成本会爆炸。

元数据的技巧

KV 中的每个键可以携带最多 1024 字节的任意 JSON 元数据,与值本身分开。该字段由 1 在一次操作中与值一起返回,无需额外的读取成本。

实际用途是将信息与您需要以其他方式解析或推断的值一起存储。对于保存在 KV 中的二进制文件,元数据可以包含23、创建日期、原始大小以及任何相关的 HTTP 标头。 Worker 在一次调用中读取密钥、接收值和元数据,并使用正确的标头组装 HTTP 响应,而无需任何额外的查找或解析逻辑。

这也适用于轻型版本控制。将上次更新的版本或时间戳保存在元数据中。任何消费者都可以检查他们是否正在阅读预期的版本,而无需搜索第二条数据。

list() 性能问题

就相对性能而言,4 是最昂贵的 KV 操作,并且它是最常出现在不应使用它的路径上的操作。在具有 10 万个键的命名空间中调用 5 速度很慢 - 延迟将取决于命名空间和游标的大小 - 并且算作一个列表操作,该操作具有单独的配额:免费套餐中每天 1000 次操作,付费套餐中每百万次操作 0.50 美元。

真正的问题是在请求的热路径中使用 6。如果每个请求都需要发现存在哪些密钥来提供响应,则您已将数据管理操作放置在关键性能路径中。

解决方案是维护一个索引键。您可以在 KV 中编写像 7 这样的键,其值是带有命名空间键列表的 JSON,或者只是逻辑所需的标识符。当命名空间发生更改时,您可以将索引与主写入一起更新。成本是每次写入操作额外写入一次。好处是任何索引读取都是常规读取,具有缓存延迟并且没有 8 的扩展问题。

这种模式有一个明显的限制,即索引需要手动保持同步。如果您有多个 Writer,KV 中缺少原子操作会在索引中产生不一致的窗口。对于具有单一写入或由单个 Writer 控制的写入的命名空间,该模式效果很好。

模块级缓存:没有人明确记录的优化

Cloudflare 上的工作程序在 V8 隔离上运行。单个隔离区在被驱逐之前可以满足数千个请求。只要隔离处于活动状态,在模块范围(处理程序外部)中声明的变量就会在请求之间持续存在。

这为配置数据创造了一个简单而有效的优化机会。您无需在每个请求中执行 9 ,而是在模块作用域中声明一个变量,并且仅在尚未初始化时搜索 KV:

0

第一个隔离请求读取 KV。对同一隔离的所有后续请求都使用内存中的值。对于很少更改的数据(产品配置、功能标志),这消除了几乎所有请求的 KV 读取,从而减少了读取操作的延迟和消耗。

这意味着 KV 的更新不会立即反映在所有 Worker 中 - 每个隔离将继续使用缓存的值,直到被驱逐。对于可接受 60 秒到几分钟延迟的数据,这种权衡是非常好的。对于需要在所有 Worker 中立即更新的数据,此模式不适合。

哪些内容不应该在没有重新考虑的情况下投入生产

使用KV作为作业队列不起作用。如果没有原子操作,两个 Worker 可以读取同一个作业,重复处理它,并将其独立地标记为完成。结果是重复处理且没有检测机制。

通过用户密钥保存可变用户数据与写入限制的扩展性很差。每天拥有 10,000 名活跃用户的应用程序,即使每个会话更新一次配置文件数据,也已经达到了每月 100 万次写入的付费限制的数量级 - 当您超出时,每次写入的成本为 0.50 美元/百万次。

具有高键密度和频繁需要列出的命名空间是一个性能陷阱。 10 在大型命名空间中速度很慢,不应该出现在请求路径中。如果您的用例需要频繁列出,则需要更改数据模型 - 要么使用手动维护的索引键,要么使用不同的工具。

免费套餐揭示了设计的哪些内容

免费套餐限制(100000 次读取和 1000 次写入)是伪装的设计文档。读和写之间的 100:1 比例并不是任意的。它描述了 KV 旨在服务的工作负载。任何反转或近似该比率的使用都超出了预期的操作模型,并且将遇到低容量测试中不会出现的成本、性能或一致性限制。

另请阅读

  • [Cloudflare KV:当你需要写12时,全球分布式是什么意思?
  • [生产中的耐用物品:法案将是什么样子以及令人惊讶的限制13
  • 【KV中的缓存失效:没人优雅解决的问题14
  • [速率限制、功能标志和分布式配置的 KV:它在哪里工作以及在哪里中断15
  • [生产中的 D1:性能、限制以及无法单独扩展的因素16
  • [KV、R2 与 Cache API:何时使用每个 Cloudflare17 存储层