一级缓存
一级缓存(L1)是数据墙DBW 内置的进程内内存缓存。它将 REST 查询结果缓存在服务进程的内存中,下次相同请求直接从内存返回,无需访问数据库。
NOTE
一级缓存仅适用于 REST 端点。GraphQL 和 MCP 当前不支持缓存。
缓存层级
数据墙DBW 的缓存分为两级:
| 层级 | 存储位置 | 共享范围 | 重启后 |
|---|---|---|---|
| L1 | 进程内存 | 单实例内 | 丢失 |
| L2 | Redis | 多实例共享 | 保留 |
可以单独使用 L1,也可以组合 L1L2 使用。不启用 L2 时,配置为 L1L2 的实体会自动退化为 L1。
全局启用缓存
必须在 runtime 中全局打开缓存开关:
json
{
"runtime": {
"cache": {
"enabled": true,
"ttl-seconds": 60
}
}
}| 字段 | 必需 | 说明 |
|---|---|---|
enabled | 是 | 全局缓存开关。不开启则所有实体的缓存无效 |
ttl-seconds | 否 | 默认的缓存生存时间(秒),实体未指定时继承此值 |
IMPORTANT
全局缓存 enabled 只是"允许"实体使用缓存。实体还需要单独开启 cache.enabled 才能实际生效。两层开关的设计允许你全局关闭所有缓存(排查问题时)而不必逐个实体修改。
实体级缓存配置
json
{
"entities": {
"Product": {
"source": { "object": "dbo.products", "type": "table" },
"cache": {
"enabled": true,
"ttl-seconds": 30,
"level": "L1"
}
},
"Order": {
"source": { "object": "dbo.orders", "type": "table" },
"cache": {
"enabled": false
}
}
}
}| 字段 | 必需 | 说明 | 默认值 |
|---|---|---|---|
enabled | 是 | 实体缓存开关 | false |
ttl-seconds | 否 | 实体级缓存生存时间(秒),覆盖全局值 | 继承全局 ttl-seconds |
level | 否 | 缓存层级:L1 或 L1L2 | L1L2 |
通过 CLI 配置
bash
dab update Product --cache.enabled true --cache.ttl-seconds 60 --cache.level "L1"缓存键与命中规则
缓存以"请求路由 + 完整查询参数"作为键。以下请求被视为不同的缓存键:
GET /api/Book → 键 A
GET /api/Book?$filter=year ge 2000 → 键 B
GET /api/Book?$first=20 → 键 C
GET /api/Book?$filter=year ge 2000&$first=20 → 键 D查询参数的任何变化(顺序除外)都会产生独立的缓存条目。
缓存失效机制
当实体发生数据写操作时,该实体相关的所有缓存条目自动失效。失效规则如下:
| 写操作 | 失效范围 |
|---|---|
POST(创建) | 该实体的全部缓存条目 |
PUT / PATCH(更新) | 该实体的全部缓存条目 |
DELETE(删除) | 该实体的全部缓存条目 |
失效是全量清除该实体的缓存,无法做到只失效与写入数据相关的那一条缓存。这意味着写操作频繁的实体不适合开启缓存——每次写入后缓存全部清空,下次读取又得重新查询数据库,缓存命中率极低。
TTL 过期
每条缓存条目都有生命周期。TTL 到期后,缓存条目自动失效,下一次相同请求会重新查询数据库并更新缓存。
- 未设置任何
ttl-seconds时,使用全局默认值(或驱动默认值 5 秒)。 - 实体级
ttl-seconds始终覆盖全局值。 - TTL 从缓存写入时开始计时,不是从首次访问计时。
L1 模式选择
纯 L1 模式(level: "L1")
json
{
"cache": {
"enabled": true,
"ttl-seconds": 30,
"level": "L1"
}
}- 缓存仅在当前进程内存中。
- 单实例部署时推荐,速度最快。
- 多实例部署时各实例缓存独立,命中率低。
L1L2 模式(level: "L1L2",默认)
当全局未启用 L2 时,实际行为退化为 L1。启用 L2 后的行为见二级缓存。
适用场景与限制
强烈推荐开启缓存
| 场景 | 原因 |
|---|---|
| 参考数据(字典、分类) | 数据基本不变,极高命中率 |
| 产品目录、文章列表 | 读多写少,更新频率以小时或天计 |
| 配置表 | 数据量小、变动少、高频访问 |
不适合开启缓存
| 场景 | 原因 |
|---|---|
| 高频写入的表 | 每次写入后缓存全部失效,命中率为零 |
| 实时性要求极高的数据 | TTL 导致的时间窗口内可能返回旧数据 |
| 写操作比读操作更频繁的表 | 缓存的维护成本超过收益 |
限制
| 限制 | 说明 |
|---|---|
| 仅 REST | GraphQL 和 MCP 查询不使用缓存 |
| 仅查询 | POST、PUT、PATCH、DELETE 操作不走缓存,但会触发失效 |
| 内存占用 | 缓存条目存储在进程内存中,大量不同查询参数组合可能导致内存增长 |
| 无预热 | 服务重启后缓存为空,需逐步通过请求填充 |
监控缓存效果
目前数据墙DBW 没有内置的缓存命中率统计端点。可以通过以下方式间接评估缓存效果:
- 对比开启/关闭缓存前后的数据库 CPU 和查询 QPS。
- 观察数据库慢查询日志中重复查询频率的变化。
- 通过 OpenTelemetry 追踪请求的端到端延迟,关注读操作的 p50/p99 指标。
