KV斯多尔
简单的密钥值存储由DynamotB支持.
何时使用 : 快速,单键的外观带有得到/put/删除语义. 对缓存、 会话存储、 特征标记和配置值都有好处 .
不使用时 : 如果您需要通过多个字段或二级索引查询,请使用 DistributedTable。如果需要完整的 SQL,请使用 Database。 。 。 .
设计与模拟等价细节 : 设计
API 密码
const store = new KVStore(scope, id, options?)
| 方法 | 回返 | 说明 |
|---|---|---|
get(key) | Promise<T | null> | 取出一分值来. 回返 null 如果缺席或期满. |
put(key, value, options?) | Promise<void> | 存储一个值 。 覆盖, 除非设置条件; 接受可选的过期 . |
delete(key, conditions?) | Promise<void> | 删除一个值. |
scan(options?) | AsyncIterable<{ key, value }> | 完成所有条目。 跳过过期的项目,除非 { includeExpired: true }. 对大型数据集具有价值. |
KVStore.fromExisting(tableName) | ExternalTableRef | 包好先前存在的DynamomDB表格. |
只有运行时间. 数据方法get, (中文(简体) ), put, (中文(简体) ), delete, (中文(简体) ), scan(按请求时间运行) ApiNamespace 方法, RawRoute 处理器、工作处理器或运行时脚本, 没有 在您的顶级 aws-blocks/index.ts。顶级代码运行于 CDK 合成期间,其中块解决其基础设施构造,其数据方法为 守护:顶级调用 Error 读取 KVStore.<method>() cannot be called during CDK synth. Data methods run at request time — …。对于种子数据,请从处理器内部或单独的运行时脚本中进行。 在模块范围构造块是好的;只有方法调用才能移动到处理器中.
选项
| 选项 | 类型 | 说明 |
|---|---|---|
schema | StandardSchemaV1 | 运行时验证计划(佐德,瓦利博特,ArkType等). 当提供时, 值类型 T 从计划中推断出 put() 写入前验证值. |
table | ExternalTableRef | 将已有的 DynamoDB 表格包起来, 而不是创建 . |
logger | ChildLogger | 内部操作的可选日志。 省略时,会在错误级别创建默认 Logger . |
removalPolicy | 'destroy' | 'retain' | 底部DynamomDB表格的移除行为. 省略时, 覆盖堆栈 defaults (从) BlocksPresets.sandbox编号 :production选择 BlocksStack.create(d) 适用—— production 保留数据于 cdk destroy, (中文(简体) ), sandbox 摧毁它。 过 'destroy'编号 :'retain' 以覆盖此商店 。 表格的删除保护也跟随堆栈 defaults。被模拟和浏览器运行时间忽略. |
ttl | boolean | 启用 DynamoDB 时间到生活,所以写有过期内容的项目会自动被删除. 默认为 false。见 过期项目。 。 。 . |
pointInTimeRecovery | boolean | { retentionDays: number } | DynamoDB 即时恢复(连续备份). true 启用默认的35天窗口; { retentionDays: n } 启用 PITR 并固定窗口(1– 说吧 –35(三); false 关闭它。 省略时, 将堆栈宽度 defaults 应用(在 production关闭在下面 sandbox) (中文(简体) ). 被模拟器和浏览器运行时间所忽略. |
encryption | 'aws-managed' | 'customer-managed' | ExternalKmsKeyRef | 服务器侧加密休息 . 'aws-managed' (默认)使用 aws/dynamodb 键; 'customer-managed' 每个表格提供专门的CMK;通过 KVStore.fromKmsKey(arn) 用于跨商店重用现有的CMK。 被模拟器和浏览器运行时间所忽略. |
过期项目( TTL)
TTL分两步选择——打开表格,然后每写一个过期:
const cache = new KVStore(scope, 'cache', { ttl: true });
// Relative expiry — delete 5 minutes from now
await cache.put('otp:alice', code, { ttlSeconds: 300 });
// Absolute expiry — a Date, or Unix epoch time in SECONDS
await cache.put('session:1', record, { expiresAt: new Date('2027-01-01') });
// No expiry — stored indefinitely (the default)
await cache.put('config:theme', 'dark');
ttl默认为false。 。 。 . 让它在已经存在的桌子上,是一个CloudFormation更新到活的桌子,所以它永远不会隐含地发生.- 属性被命名
ttl。 。 。 . 只有当ttlSeconds或者说expiresAt被提供,它拥有Unix时代 秒数。 。 。 . ttlSeconds财务报告和审定财务报表expiresAt两者相互排斥. 通过两者——或一个看上去是划时代毫秒的值——抛出ValidationFailedException而不是默默地储存一年 -5138期满.- 读取从不返回过期的项目 . DynamoDB的收割者是同步的(一般在48小时内),所以
get返回时null财务报告和审定财务报表scan在每次运行时跳过一个项目. - 过期为一写. 重新投放没有过期选项的密钥可以清除任何先前的过期;重新投放时可以向前滑出.
- TTL 用有条件的写道:
put(key, value, { ifNotExists: true, ttlSeconds: 60 })。 。 。 .
TTL是一种保留控制,而不是授权控制. 任何对安全敏感(会话有效性、撤销令牌)都必须在读取时检查.
有条件的操作
两者 put 财务报告和审定财务报表 delete 接受可选选项对象:
// Only write if key doesn't exist (idempotent create)
await store.put('user:alice', data, { ifNotExists: true });
// Only write if current value matches (optimistic locking / compare-and-swap)
await store.put('counter', newVal, { ifValueEquals: oldVal });
// Compose both (OR): create it, or update it only if unchanged — write succeeds
// if the key is absent OR its current value matches; fails only if it exists and differs.
await store.put('config', next, { ifNotExists: true, ifValueEquals: prev });
// Only delete if key exists
await store.delete('temp', { ifExists: true });
// Only delete if value matches
await store.delete('lock', { ifValueEquals: expectedVal });
所有条件失败 error.name === KVStoreErrors.ConditionalCheckFailed序列化为JSON-RPC 409 (冲突) 以铁丝网盟誓 error.status === 409 客户端和 isBlocksError 仍然与名字相符。 标出冲突 可回收 当一个值检查参与时( stale- value 乐观- 锁定冲突—— 重新读取和重试可能成功) 。 对于 put, (中文(简体) ), ifNotExists 财务报告和审定财务报表 ifValueEquals 用OR来作曲,所以每次失败 ifValueEquals ——包括合并 ifNotExists+ 键ifValueEquals 例 —— 是 stale- value 案, 并且可以收回; 纯 ifNotExists put 冲突是 没有 可还. 对于 delete (独立检查,不是OR),纯 ifExists 冲突——或合并 ifExists+ 键ifValueEquals 冲突——即 没有 可回收; 只有值 ifValueEquals 删除冲突为。 盲目重试不可挽回的冲突同样失败.
处理错误
| 常数 | error.name | 掷出时 |
|---|---|---|
KVStoreErrors.ConditionalCheckFailed | ConditionalCheckFailedException | 一个 ifNotExists 编号 : ifExists 编号 : ifValueEquals 条件失败 。 序列化为 HTTP 409 (冲突); 当值检查参与时可检索(任何) put 冲突 ifValueEquals 被设定,因为 put 由 OR 组成; 仅值 ifValueEquals delete (冲突)——对纯净人来说是无法补偿的 ifNotExists put 或任何 ifExists delete。 。 。 . |
KVStoreErrors.ValidationFailed | ValidationFailedException | 配置失败的值 schema 审定. |
KVStoreErrors.ItemTooLarge | ItemTooLargeException | 串行物品超过400KB DynamomDB每件物品尺寸限制. (在AWS层中,DynamoDB提出一个通用 ValidationException; KVStore 将大小特异性大小的大小例重绘为此名. ) |
import { isBlocksError } from '@aws-blocks/core';
import { KVStoreErrors } from '@aws-blocks/bb-kv-store';
try {
await store.put('key', value, { ifNotExists: true });
} catch (e: unknown) {
if (isBlocksError(e, KVStoreErrors.ConditionalCheckFailed)) {
// key already exists
}
if (isBlocksError(e, KVStoreErrors.ItemTooLarge)) {
// value is too large — consider compressing or splitting
}
throw e;
}
实例
基本使用(字符串值)
const store = new KVStore(scope, 'cache');
export const api = new ApiNamespace(scope, 'api', (context) => ({
async setGreeting(value: string) {
await store.put('greeting', value);
},
async getGreeting() {
return { value: await store.get('greeting') };
},
}));
没有 schema,默认值类型为 string。要存储结构化数据而不进行运行时间验证,请通过类型参数—— new KVStore<MyType>(scope, id); 数值在写入时为 JSON 序列化,在读取时自动解析( 没有手动) JSON.stringify a. 组织事项.
用 Schema 键入的值
使用一个图案以获得运行时间验证的类型安全值 :
这些例子使用Zod,但
schema接受任何标准SchemaV1执行(Zod, Valibot, ArkType). 安装您选择的库, 例如 .npm install zod。 。 。 .
import { z } from 'zod';
const sessionSchema = z.object({
userId: z.string(),
expiresAt: z.number(),
});
const sessions = new KVStore(scope, 'sessions', { schema: sessionSchema });
// Type is inferred from the schema — no generic arg needed
await sessions.put(token, { userId: 'alice', expiresAt: Date.now() + 3600000 });
const session = await sessions.get(token); // { userId: string; expiresAt: number } | null
// Invalid data is rejected at runtime
await sessions.put(token, { userId: 123 }); // throws ValidationFailedException
环绕已存在的表格
const legacy = new KVStore(scope, 'legacy', {
table: KVStore.fromExisting('my-existing-table'),
});
最佳做法
- 保持密钥简短和描述性(例如,
user:{id}, (中文(简体) ),session:{token}(中文(简体) ) - 每个 KVStore 实例存储一个逻辑实体
- 使用一个
schema对于结构值——它确保运行时间数据与您的类型匹配 - 使用
{ ifNotExists: true }用于生成偶数 - 使用
{ ifValueEquals }当多个作者有可能时,用于比较和扫描 scan()返回一个AsyncIterable- 与await Array.fromAsync(store.scan())或者说for await. 偏爱get(key)结束scan()(扫描仪读取每件物品).
缩放成本( AWS)
- 计费: PAY PER REQENT - 没有提供管理能力
- 延迟 : 读取和写出数位数
- 通过量 : 自动缩放, 表格大小无上限
- 项目大小限制 : 每件400KB
- 费用: ~每百万人有1.25美元,~每百万人有0.25美元
- 重复性 : 99.99999999999%(119%),跨越3个AZ
地方发展
模拟数据持续到磁盘 .bb-data/{fullId}/ 跨 Dev 服务器重启 。 擦拭为 rm -rf .bb-data。模拟验证了400 KB 项的尺寸限制、 计划验证以及有条件的检查失败, 符合 AWS 行为.