缓存存储昂贵操作(数据库查询、计算、外部 API 调用)的结果,这样重复请求可以快速响应而无需重复工作。它是 API 性能优化中影响最大的优化之一。
内存缓存(最快,单实例)
js
cache = ();
() {
(cache.(id)) cache.(id);
user = db.(id);
cache.(id, user);
user;
}
缓存存储昂贵操作(数据库查询、计算、外部 API 调用)的结果,这样重复请求可以快速响应而无需重复工作。它是 API 性能优化中影响最大的优化之一。
cache = ();
() {
(cache.(id)) cache.(id);
user = db.(id);
cache.(id, user);
user;
}
简单且极其快速,但缓存是每进程的(不在实例间共享),重启时丢失。适合小的热数据——但需要驱逐策略(使用 lru-cache 等 LRU 缓存)来限制内存占用。
import { createClient } from "redis";
const redis = createClient();
async function getUser(id) {
const cached = await redis.get(`user:${id}`);
if (cached) return JSON.parse(cached); // hit
const user = await db.findUser(id);
await redis.setEx(`user:${id}`, 3600, JSON.stringify(user)); // cache for 1h (TTL)
return user;
}
Redis 是跨多个服务器实例缓存的标准方案——一个共享的、快速的存储,能存活于重启并随应用扩展。TTL(生存时间)会自动过期条目,所以数据不会永久保持过时。
res.set("Cache-Control", "public, max-age=3600"); // browsers/CDN cache for 1h
res.set("ETag", hash); // conditional requests (304 Not Modified)
HTTP 缓存头将缓存完全卸载到浏览器和 CDN——最快的缓存是永远不到达你服务器的请求。
// when data changes, the cache must be updated or cleared, or users see stale data
async function updateUser(id, data) {
await db.updateUser(id, data);
await redis.del(`user:${id}`); // INVALIDATE — next read repopulates with fresh data
}
最大的缓存挑战是失效——确保更新清除/刷新受影响的缓存条目,这样用户看不到过时数据。策略包括:TTL(接受短暂的过时)、写穿(写时更新缓存)或在修改时显式删除。
✓ Read-heavy, infrequently-changing data (config, product catalogs, user profiles)
✓ Expensive computations, external API responses
✗ Highly dynamic/personalized or rapidly-changing data (or use very short TTLs)
✗ Sensitive data without care for who can read the cache
缓存能大幅降低延迟和数据库/外部服务的负载,通常是慢 API 和快速、可扩展 API 的区别。
理解各层——内存缓存(最快,每实例,用 LRU 限制)、Redis(跨实例共享)和 HTTP/CDN 缓存(完全卸载)——让你能选择正确的策略。
理解缓存的核心难题,失效(通过 TTL 或写时显式清除),是防止经典权衡失败(用户看到过时数据)的关键。
有效的缓存是 API 性能和可扩展性最有影响力的工具之一。
一个包含详细解答的 IT 面试题库——从初级到高级。
捐赠