以下是客户端缓存、API网关缓存、服务层缓存和数据库缓存的具体定义及其核心特性:
1. 客户端缓存(Client-Side Caching)
定义
在客户端(如浏览器、移动端应用)本地存储数据或资源副本,减少对服务端的重复请求。
核心特性
- 位置:客户端设备(浏览器内存、LocalStorage、Service Worker 缓存等)
- 目的:
- 减少网络请求次数
- 提升用户感知性能(快速加载本地资源)
- 典型技术:
- HTTP 缓存头(
Cache-Control
,ETag
) - Service Worker(离线缓存)
- Web Storage(LocalStorage/SessionStorage)
- HTTP 缓存头(
- 适用场景:
- 静态资源(JS/CSS/图片)
- 低频更新的 API 响应(如用户配置信息)
- 示例(Node.js/Express):
1
2
3
4
5// 设置 HTTP 缓存头(强制浏览器缓存 1 小时)
app.get("/static/logo.png", (req, res) => {
res.setHeader("Cache-Control", "public, max-age=3600");
// 发送图片数据...
});
注意事项
- 需管理缓存版本(如通过文件哈希值命名资源)
- 强缓存可能导致用户获取过期数据(需配合协商缓存策略)。
2. API 网关缓存(API Gateway Caching)
定义
在 API 网关层缓存完整的 HTTP 响应,直接返回缓存结果,避免请求穿透到下游服务。
核心特性
- 位置:API 网关(微服务架构的入口层,如 Nginx、Kong 或自定义网关)
- 目的:
- 减少后端服务负载
- 统一管理高频 API 的缓存策略
- 典型技术:
- Redis/Memcached(分布式缓存)
- Nginx 代理缓存
- 网关中间件(如 Express + Redis 实现)
- 适用场景:
- 高频读请求(如商品详情页 API)
- 无需实时一致性的数据(如新闻列表)
- 示例(Node.js + Redis):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 网关中间件缓存 API 响应
const cacheMiddleware = async (req, res, next) => {
const cacheKey = req.originalUrl;
const cachedResponse = await redis.get(cacheKey);
if (cachedResponse) {
res.send(JSON.parse(cachedResponse)); // 直接返回缓存
return;
}
// 未命中缓存时继续处理并存储结果
const originalSend = res.send;
res.send = (body) => {
redis.setex(cacheKey, 300, body); // 缓存 5 分钟
originalSend.call(res, body);
};
next();
};
注意事项
- 需根据请求参数区分缓存键(如
GET /users?id=123
和id=456
应缓存为不同键) - 敏感数据需设置缓存隔离(如按用户 ID 分组)。
3. 服务层缓存(Service Layer Caching)
定义
在业务服务内部缓存数据(如数据库查询结果、计算中间值),减少重复计算或 IO 操作。
核心特性
- 位置:业务服务进程内或专用缓存服务(如 Redis 集群)
- 目的:
- 降低数据库负载
- 加速服务内部数据处理
- 典型技术:
- 内存缓存(Node.js 的
node-cache
、lru-cache
) - 分布式缓存(Redis)
- 内存缓存(Node.js 的
- 适用场景:
- 热点数据(如秒杀商品库存)
- 复杂计算结果(如排行榜数据)
- 示例(Node.js 内存缓存):
1
2
3
4
5
6
7
8
9
10
11
12const NodeCache = require("node-cache");
const cache = new NodeCache({ stdTTL: 60 }); // 默认缓存 60 秒
async function getUserProfile(userId) {
const cacheKey = `user_profile_${userId}`;
let profile = cache.get(cacheKey);
if (!profile) {
profile = await db.query("SELECT * FROM users WHERE id = ?", [userId]);
cache.set(cacheKey, profile);
}
return profile;
}
注意事项
- 进程内缓存无法跨服务共享(需结合分布式缓存)
- 需防止缓存雪崩(随机 TTL 或互斥锁)。
4. 数据库缓存(Database Caching)
定义
在数据库层缓存查询结果或索引数据,加速后续相同查询。
核心特性
- 位置:数据库服务器内部或外部缓存(如 Redis 旁路缓存)
- 目的:
- 减少磁盘 IO
- 加速复杂查询(如聚合操作)
- 典型技术:
- 数据库内置缓存(MySQL Query Cache、MongoDB 缓存引擎)
- 外部缓存(Redis 作为数据库前置缓存)
- 适用场景:
- 重复的复杂查询(如报表统计 SQL)
- 高频读取的静态数据(如国家城市列表)
- 示例(Redis 旁路缓存):
1
2
3
4
5
6
7
8
9async function getProductFromDB(id) {
const cacheKey = `db_product_${id}`;
let product = await redis.get(cacheKey);
if (!product) {
product = await db.query("SELECT * FROM products WHERE id = ?", [id]);
redis.setex(cacheKey, 3600, JSON.stringify(product)); // 缓存 1 小时
}
return JSON.parse(product);
}
注意事项
- 数据库内置缓存可能因写操作自动失效(如 MySQL 表更新时清空相关缓存)
- 旁路缓存需手动维护一致性(如双写策略或监听数据库变更日志)。
四层缓存对比总结
缓存类型 | 位置 | 缓存内容 | 一致性要求 | 适用场景 |
---|---|---|---|---|
客户端缓存 | 用户设备 | HTTP 响应/静态资源 | 弱一致性(可接受过期) | 静态资源、用户配置 |
API 网关缓存 | 网关层 | 完整 API 响应 | 中等一致性(分钟级) | 高频 API(如商品详情) |
服务层缓存 | 业务服务内部 | 业务数据对象 | 强一致性(秒级) | 热点数据、复杂计算结果 |
数据库缓存 | 数据库层 | 查询结果集 | 强一致性(实时) | 复杂 SQL、高频读取数据 |
选择建议
- 客户端缓存:优先用于减少网络传输(如 CDN + 浏览器缓存静态资源)。
- API 网关缓存:适合统一管理高频且对实时性要求不高的 API。
- 服务层缓存:用于保护数据库(如缓存热点数据,避免直接冲击数据库)。
- 数据库缓存:作为最后防线,缓存复杂查询结果(需谨慎处理一致性)。
通过分层缓存策略,可构建高性能、高可用的系统架构,同时需权衡缓存一致性、复杂度和维护成本。