Durable Object Storage API 允许 Durable Objects 访问事务性且强一致的存储。Durable Object 的附加存储对其唯一实例私有,其他对象无法访问。
Durable Object Storage API 提供多种方法,包括 SQL、时间点恢复(PITR)、键值(KV)和 alarm API。可用 API 方法取决于 Durable Objects 类的存储后端,即 SQLite 或 KV。
| 方法 1 | SQLite 支持的 Durable Object 类 | KV 支持的 Durable Object 类 |
|---|---|---|
| SQL API | ✅ | ❌ |
| PITR API | ✅ | ❌ |
| 同步 KV API | ✅ 2, 3 | ❌ |
| 异步 KV API | ✅ 3 | ✅ |
| Alarms API | ✅ | ✅ |
脚注
1 每个方法都隐式包装在事务中,使其结果具有原子性,并与所有其他存储操作隔离,即使访问多个键值对也是如此。
2 像 get()、put()、delete() 或 list() 这样的 KV API 方法将数据存储在隐藏的 SQLite 表 __cf_kv 中。请注意,列出所有表时可以查看此表,但无法通过 SQL API 访问其内容。
3 SQLite 支持的 Durable Objects 还使用 ctx.storage.kv 的同步 KV API 方法,而 KV 支持的 Durable Objects 仅提供异步 KV API 方法。
Durable Objects 通过 DurableObjectStorage 接口访问 Storage API,并通过 DurableObjectState::storage 属性访问。通常通过传递给 Durable Object 构造函数的 ctx 参数的 this.ctx.storage 访问。
以下代码片段展示如何使用 Durable Object Storage API 存储和检索数据。
export class Counter extends DurableObject {
constructor(ctx, env) {
super(ctx, env);
}
async increment() {
let value = (await this.ctx.storage.get("value")) || 0;
value += 1;
await this.ctx.storage.put("value", value);
return value;
}
}export class Counter extends DurableObject {
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
}
async increment(): Promise<number> {
let value: number = (await this.ctx.storage.get("value")) || 0;
value += 1;
await this.ctx.storage.put("value", value);
return value;
}
}from workers import DurableObject
class Counter(DurableObject):
def __init__(self, ctx, env):
super().__init__(ctx, env)
async def increment(self):
value = (await self.ctx.storage.get("value")) or 0
value += 1
await self.ctx.storage.put("value", value)
return valueJavaScript 是一种单线程和事件驱动的编程语言。这意味着 JavaScript 运行时默认允许请求相互交错,可能导致并发 bug。Durable Objects 运行时使用 input gate 和 output gate 的组合,在执行存储操作时避免此类并发 bug。在我们的博客文章 ↗中了解更多。
KV 支持的 Durable Objects 提供异步的 KV API 方法。
ctx.storage.get(key:string, optionsObjectoptional)Promise<any>- 检索与给定键关联的值。返回值的类型将是先前为该键写入的任何类型,如果键不存在则为 undefined。
ctx.storage.get(keys:Array<string>, optionsObjectoptional)Promise<Map<string, any>>- 检索与每个提供的键关联的值。
Map↗ 中每个返回值的类型将是先前为对应键写入的任何类型。Map中的结果按 UTF-8 编码升序排序,任何不存在的请求键将被省略。一次最多支持 128 个键。
- 检索与每个提供的键关联的值。
allowConcurrency:boolean- 默认情况下,系统在存储操作进行时暂停向 Object 传递 I/O 事件,以避免意外的竞态条件。传递
allowConcurrency: true以选择退出此行为并允许传递并发事件。
- 默认情况下,系统在存储操作进行时暂停向 Object 传递 I/O 事件,以避免意外的竞态条件。传递
noCache:boolean- 如果为 true,则键/值不会插入内存缓存。如果键已在缓存中,将返回缓存值,但其 last-used 时间不会更新。当你预期此键在近期不会再次使用时使用。此标志仅为提示。此标志永远不会改变代码的语义,但可能影响性能。
put(key:string, valueany, optionsObjectoptional)Promise-
存储值并将其与给定键关联。值可以是 structured clone algorithm ↗ 支持的任何类型,大多数类型都符合。
键和值的大小限制取决于你使用的 Durable Object 存储后端。请参阅:
在 KV 支持的 Durable Object 上,如果序列化值超过 128 KiB(131072 字节)值大小限制,
put()在应用写入之前抛出RangeError(例如Values cannot be larger than 131072 bytes.)。
-
put(entries:Object, optionsObjectoptional)Promise- 接受 Object 并将其每个键和值存储到 storage。
- 每个值可以是 structured clone algorithm ↗ 支持的任何类型,大多数类型都符合。
- 一次最多支持 128 个键值对。键和值的大小限制取决于你使用的 Durable Object 类型。请参阅:
delete(key:string, optionsObjectoptional)Promise<boolean>- 删除键及关联值。如果键存在则返回
true,否则返回false。
- 删除键及关联值。如果键存在则返回
delete(keys:Array<string>, optionsObjectoptional)Promise<number>- 删除提供的键及其关联值。一次最多支持 128 个键。返回删除的键值对数量。
-
put()、delete()和deleteAll()支持以下 options: allowUnconfirmedboolean-
默认情况下,系统将暂停 Durable Object 的传出网络消息,直到所有先前的写入都已确认刷新到磁盘。如果写入失败,系统将重置 Object、丢弃所有传出消息,并向任何客户端返回错误。
-
这样,Durable Objects 可以与写入操作并行继续执行,而无需担心过早确认写入,因为除非写入实际成功,否则任何外部方都无法观察 Object 的操作。
-
任何写入后,后续网络消息可能会略有延迟。某些应用可能认为基于未确认写入进行通信是可以接受的。某些程序可能希望立即允许网络流量。在这种情况下,将
allowUnconfirmed设置为true以选择退出默认行为。 -
如果你希望某些传出网络消息立即继续但不希望其他消息继续,可以使用 allowUnconfirmed 选项避免阻塞你希望继续的消息,然后单独调用
sync()方法,该方法返回的 promise 仅在所有先前的写入成功持久化到磁盘后才 resolve。
-
noCacheboolean-
如果为 true,则键/值在完成写入磁盘后立即从内存中丢弃。
-
如果键在近期不会再次使用,请使用
noCache。noCache永远不会改变代码的语义,但可能影响性能。 -
如果你在写入完成之前使用
get()检索键,将返回写入缓冲区中的副本,从而确保与最新put()调用的一致性。
-
list(options:Objectoptional)Promise<Map<string, any>>
startstring- list 结果应开始的键(含)。
startAfterstring- list 结果应在其后开始的第一键(不含)。不能与
start同时使用。
- list 结果应在其后开始的第一键(不含)。不能与
endstring- list 结果应结束的键(不含)。
prefixstring- 将结果限制为仅包含键以该前缀开头的键值对。
reverseboolean- 如果为 true,以降序而非默认升序返回结果。
- 启用
reverse不会改变start、startKey或endKey的含义。start仍定义可按字典序返回的最小键(含), effectively 作为逆序 list 的端点。end仍定义 list 应考虑的最大键(不含), effectively 作为逆序 list 的起点。
limitnumber- 返回的最大键值对数量。
allowConcurrencyboolean- 与上述
get()的 option 相同。
- 与上述
noCacheboolean- 与上述
get()的 option 相同。
- 与上述
getAlarm(options:Objectoptional)Promise<Number | null>- 获取当前 alarm 时间(如果已设置),以自 epoch 起的整数毫秒表示。如果 alarm 尚未开始,或已失败且任何重试尚未开始,则视为已设置 alarm。如果未设置 alarm,
getAlarm()返回null。
- 获取当前 alarm 时间(如果已设置),以自 epoch 起的整数毫秒表示。如果 alarm 尚未开始,或已失败且任何重试尚未开始,则视为已设置 alarm。如果未设置 alarm,
- 与
get()相同的选项,但不包含noCache。
setAlarm(scheduledTime:Date | number, optionsObjectoptional)Promise- 设置当前 alarm 时间,接受 JavaScript
Date或自 epoch 起的整数毫秒。
如果使用等于或早于
Date.now()的时间调用setAlarm(),alarm 将被安排在近期异步执行。如果此时 alarm 处理程序正在执行,它不会被取消。Alarm 可精确到毫秒级,通常会在设定时间后几毫秒内执行,但由于维护或故障转移期间的故障,可能会延迟最多一分钟。- 设置当前 alarm 时间,接受 JavaScript
deleteAlarm(options:Objectoptional)Promise- 如果存在 alarm 则删除。如果 alarm 处理程序当前正在执行,不会取消该处理程序。
setAlarm()和deleteAlarm()支持与put()相同的选项,但不包含noCache。
deleteAll(options:Objectoptional)Promise- 删除所有存储的数据,实际释放 Durable Object 使用的所有存储。对于键值存储后端的 Durable Objects,
deleteAll()删除单个 Durable Object 的所有键和关联值。对于 SQLite 存储后端 的 Durable Objects,deleteAll()删除 Durable Object 私有 SQLite 数据库的全部内容,包括 SQL 数据和键值数据。 - 对于键值存储后端的 Durable Objects,进行中的
deleteAll()操作可能失败,可能留下部分未删除的数据。SQLite 存储后端的 Durable Objects 没有部分deleteAll()问题,因为deleteAll()操作是原子的(全有或全无)。 - 对于兼容日期为
2026-02-24或更晚的 Workers,deleteAll()还会删除任何活动的 alarm。对于较早的兼容日期,deleteAll()不会删除 alarm。请单独使用deleteAlarm(),或启用delete_all_deletes_alarm兼容性标志。
- 删除所有存储的数据,实际释放 Durable Object 使用的所有存储。对于键值存储后端的 Durable Objects,
transactionSync(callback):any-
仅在使用 SQLite 支持的 Durable Objects 时可用。
-
在事务中包装
callback()并调用,返回其结果。 -
如果
callback()抛出异常,事务将回滚。 -
回调必须同步完成,即不应声明为
async或以其他方式返回 Promise。只有同步存储操作可以是事务的一部分。这旨在与使用ctx.storage.sql.exec()的 SQL 查询一起使用,这些查询同步完成。
-
transaction(closureFunction(txn)):Promise-
在单个事务中运行
txn上调用的存储操作序列,该事务要么成功提交要么中止。 -
显式事务不再必要。在没有中间
await的情况下调用的任何一系列写入操作将自动原子提交,系统在await读取操作时将阻止并发事件执行(除非你使用allowConcurrency: true)。因此,一系列读取后接一系列写入(中间没有其他 I/O)自动具有原子性,行为类似事务。
-
-
txn-
提供对上面记录的
put()、get()、delete()和list()方法的访问,以在当前事务上下文中运行。要在事务闭包中获得事务行为,必须在txnObject 上调用方法,而不是在顶层ctx.storageObject 上。
还支持rollback()函数,确保事务期间所做的任何更改将被回滚而非提交。调用rollback()后,txnObject 上的任何后续操作都将失败并抛出异常。rollback()不接受参数且不向调用方返回任何内容。 -
使用 SQLite 存储引擎 时,
txn对象已过时。直接在ctx.storageObject 上执行的任何存储操作,包括使用ctx.storage.sql.exec()的 SQL 查询,都将被视为事务的一部分。
-
sync():Promise-
将任何待处理的写入同步到磁盘。
-
这类似于自动写入合并的正常行为。如果写入缓冲区中有任何待处理的写入(包括通过
allowUnconfirmed选项 提交的写入),返回的 promise 将在它们完成时 resolve。如果没有待处理的写入,返回的 promise 将已 resolve。
-