Redis 如何将我的数据库读取从约 26K 降至几乎为零
Source: Dev.to

我过去在每一次页面加载时都直接请求 Supabase——博客、单篇文章、经历、工具箱、服务、连接、个人信息、角色可见性、技能……基本上我的整个个人仪表盘都依赖于直接的数据库查询。
结果是?
- 约 26,000 次数据库读取/天
- 响应缓慢
- 不必要的负载
- 偶尔的连接警告
于是,我引入了 Redis 作为读穿缓存,并配合一个小型的 预热脚本——一切都改变了。
我缓存的内容
我专注于 最热的读取密集型数据:
- 博客 → 已发布列表、单篇数据、合并的博客负载
- 经历 → 活跃的 + 完整历史
- 工具箱 → 全部、软件、硬件
- 服务 → 活跃的 + 全部
- 连接 → 完整列表
- 个人信息 → 单例记录
- 角色可见性 → 侧边栏 & 快捷操作
- 技能 → 完整列表 + 类别变体
这些是完美的 缓存候选,因为它们:
- 更改频率低
- 被持续读取
- 不需要实时一致性
Source: …
缓存工作原理
1) 读取穿透缓存模式
每个 GET 接口都包装了一个辅助函数:
getCached(key, fetcher, ttl = 300)
流程
请求 → 检查 Redis
→ 缓存命中 → 立即返回
→ 缓存未命中 → 从 Supabase 获取 → 存入 Redis → 返回
- 只有第一次请求会访问数据库
- 其余所有请求 在毫秒级从 Redis 提供服务
2) 写入时的智能失效
当数据通过 POST、PUT 或 DELETE 发生变化时,我会调用:
invalidateKeys([...])
这只会清除 受影响的缓存前缀,保持一切:
- 新鲜
- 一致
- 快速
3) 预热缓存
为避免部署后出现冷启动延迟,我编写了一个脚本:
scripts/prewarm-redis.mjs
它仅调用 公共 API 接口——不需要数据库凭证。
运行方式如下:
BASE_URL=http://localhost:3000 node scripts/prewarm-redis.mjs
现在 Redis 在真实用户到来之前已经 全部填充。
4) 可视化与健康监控
我在 Data tab UI 中添加了显示:
- Redis 健康状态
- 缓存项目总数
- 缓存数据集概览
如果 Redis 出现故障,我能立刻发现。
结果 📉
使用 Redis 前
- ~26K 每日数据库读取
- 延迟更高
- 存在最大连接数限制的风险
使用 Redis 后
- 冷启动: 每个数据集仅一次数据库访问
- 热流量: 几乎为零的数据库读取
- 延迟: 单位毫秒级
- 稳定性: 没有连接压力
简而言之: 数据库成为备份;Redis 成为主要读取层。
最大差异的关键因素
- 缓存最热的读取 – 当列表和单例数据被缓存时,可带来巨大的投资回报率。
- 保持 TTL 适度 – 我使用 5 分钟 来平衡新鲜度和性能。
- 部署时始终预热 – 完全消除冷启动惩罚。
- 监控缓存健康 – 可视性防止静默的性能回退。
如何尝试
-
配置 Redis
REDIS_URL=... # or host/port/user/password -
启动你的应用
-
运行预热脚本
-
打开仪表盘/博客页面
观察:
- 数据库指标下降
- Redis 命中率上升
- 延迟缩短
最终思考
添加 Redis 不仅是一次 性能优化——它从根本上改变了我的应用在 大规模读取 时的处理方式。
从:
“每次都查询数据库”
到:
“从内存即时提供,只有在必要时才访问数据库。”
这一次转变将 每日 26K 次读取降低到几乎为零。
而最棒的是?实现时间不到一天。