feat(db): 统一元数据缓存层 MetadataCache
- 两级:L1 进程内存(按 region 限条数的 LRU、5 分钟)+ L2 PG kv_cache;读 L1 → L2 → 源,写两级 - 迁移 0086:kv_cache 加 fresh_until(过期先用旧值的宽限期)与 pinned(LRU 淘汰跳过);新表 cache_stat 按天 × region 汇总命中 - stale-while-revalidate:宽限期 = TTL 的 50%(上限 7 天),旧值先返回、同 key 后台只刷一次,刷新失败继续用旧值并记警告 - 同进程同 key 并发只回源一次;回源抛错不缓存;PG 读写失败按未命中 / 不写处理 - PgCache.delete / clear 发 pg_notify(umt_cache_invalidate),listenCacheInvalidation 收到后丢 L1;监听在线才启用 L1,断线停用、重连后整体清空 - PgCache.get 只认新鲜条目,getEntry 带回旧值;renew 只续新鲜条目并可标 pinned Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
0f656f0f58
commit
ad472a1a19
7 files changed
+815
-17
No files matched your search
@@ -0,0 +1,41 @@
|
||||
import type { Kysely } from "kysely";
|
||||
import { dropTables, execDdl } from "../src/migration-helpers.ts";
|
||||
|
||||
// 统一元数据缓存(docs/runbook/cache.md):
|
||||
// - kv_cache.fresh_until:新鲜期截止。过了 fresh_until、还没到 expires_at 的条目是「旧值」:
|
||||
// MetadataCache 先返回旧值再后台刷新(stale-while-revalidate);PgCache.get 只返回新鲜条目。null = 没有宽限期。
|
||||
// - kv_cache.pinned:关注中作品的条目,写入时按条数上限淘汰(LRU)跳过它们;到期仍会过期。
|
||||
// - cache_stat:按天 × region 汇总各进程的命中统计(进程内计数,定期把增量加进来)。
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: 迁移不依赖应用表类型
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await execDdl(
|
||||
db,
|
||||
`
|
||||
alter table kv_cache add column fresh_until timestamptz;
|
||||
alter table kv_cache add column pinned boolean not null default false;
|
||||
create table cache_stat (
|
||||
day date not null,
|
||||
region text not null,
|
||||
l1_hits bigint not null default 0,
|
||||
l2_hits bigint not null default 0,
|
||||
stale_hits bigint not null default 0,
|
||||
misses bigint not null default 0,
|
||||
failures bigint not null default 0,
|
||||
refreshes bigint not null default 0,
|
||||
updated_at timestamptz not null default now(),
|
||||
primary key (day, region)
|
||||
);
|
||||
`,
|
||||
);
|
||||
}
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: 同上
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await execDdl(
|
||||
db,
|
||||
`${dropTables(["cache_stat"])}
|
||||
alter table kv_cache drop column if exists pinned;
|
||||
alter table kv_cache drop column if exists fresh_until;`,
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user