Node.js + Redis 实战:实现高效分布式缓存与限流策略
前言
在高并发 Web 应用中,数据库查询、API 请求、并发操作 是影响系统性能和稳定性的关键因素。Redis 作为一个高性能的内存数据库,可以有效缓解这些问题,为 Web 应用提供 缓存、限流、分布式锁、消息队列 等功能。
本篇文章将通过大量代码示例,深入剖析如何使用 Node.js + Redis 实现:
✅ 高效缓存:减少数据库查询,提升 API 响应速度
✅ 会话存储(Session):支持用户状态管理
✅ 分布式锁:防止超卖等并发问题
✅ API 限流:防止恶意请求,保障系统稳定
✅ 数据淘汰策略(TTL + LRU):优化 Redis 内存使用
✅ Redis 连接池优化:提高系统吞吐量
👉 适用场景:高并发 Web 应用、微服务、API 网关、IoT 设备等。
🚀 通过实战代码,全面掌握 Redis 在 Node.js 高并发系统中的应用!
一、环境准备
1.1 安装 Redis
使用 Docker 快速安装:
docker run -d --name redis -p 6379:6379 redis
本地安装(适用于 macOS/Linux):
brew install redis # macOS
sudo apt install redis # Ubuntu
验证 Redis 运行
redis-cli ping # 预期返回:PONG
1.2 安装 Node.js 依赖
npm init -y
npm install express ioredis express-session connect-redis
二、Redis 作为缓存层(加速数据库查询)
2.1 连接 Redis
const Redis = require("ioredis");
const redis = new Redis(); // 连接本地 Redis
2.2 基于 Redis 缓存 API 响应
const express = require("express");
const app = express();
const fetchUserFromDB = async (id) => {
console.log("查询数据库...");
return { id, name: `User${id}`, age: Math.floor(Math.random() * 30) + 20 };
};
app.get("/user/:id", async (req, res) => {
const { id } = req.params;
const cacheKey = `user:${id}`;
// 先查 Redis
const cachedUser = await redis.get(cacheKey);
if (cachedUser) {
return res.json({ source: "cache", data: JSON.parse(cachedUser) });
}
// 数据库查询
const user = await fetchUserFromDB(id);
// 存入 Redis,过期时间 10 分钟
await redis.setex(cacheKey, 600, JSON.stringify(user));
res.json({ source: "database", data: user });
});
app.listen(3000, () => console.log("Server running on port 3000"));
效果
- 第一次请求:查询数据库,并将结果缓存到 Redis
- 之后的请求:直接从 Redis 读取,加速 API 响应
三、Redis 作为会话存储(Session 管理)
3.1 安装 express-session
和 connect-redis
npm install express-session connect-redis
3.2 使用 Redis 存储 Session
const session = require("express-session");
const RedisStore = require("connect-redis").default;
app.use(
session({
store: new RedisStore({ client: redis }),
secret: "super-secret-key",
resave: false,
saveUninitialized: false,
cookie: { secure: false, maxAge: 60000 }
})
);
// 登录接口
app.get("/login", (req, res) => {
req.session.user = { id: 1, name: "Alice" };
res.send("登录成功");
});
// 获取 Session
app.get("/profile", (req, res) => {
res.json(req.session.user || "未登录");
});
效果
- 用户登录信息存入 Redis
- 其他 API 直接读取 Session
四、Redis 分布式锁(防止超卖)
4.1 传统超卖问题
在高并发情况下,多个用户同时购买商品,可能导致库存变成负数:
let stock = 5;
app.get("/buy", (req, res) => {
if (stock > 0) {
stock--;
res.send(`购买成功!剩余库存:${stock}`);
} else {
res.send("库存不足");
}
});
并发请求可能会让
stock
变成负数!
4.2 使用 Redis 实现分布式锁
const acquireLock = async (lockKey, expireTime = 5) => {
return await redis.set(lockKey, "LOCKED", "NX", "EX", expireTime);
};
const releaseLock = async (lockKey) => {
await redis.del(lockKey);
};
app.get("/buy", async (req, res) => {
const lockKey = "lock:product";
if (!await acquireLock(lockKey)) {
return res.status(429).send("系统繁忙,请稍后再试");
}
let stock = await redis.get("product_stock") || 10;
if (stock > 0) {
stock--;
await redis.set("product_stock", stock);
res.send("购买成功!剩余库存:" + stock);
} else {
res.send("库存不足");
}
await releaseLock(lockKey);
});
效果
- 防止多个请求同时修改库存
- 避免超卖问题
五、Redis 实现 API 限流
5.1 限流策略
算法 | 说明 |
---|---|
固定窗口 | 每分钟最多 N 次请求 |
滑动窗口 | 根据时间动态调整 |
令牌桶 | 允许突发流量,但受限于令牌速率 |
5.2 使用 Redis 计数器进行限流
const rateLimit = async (ip) => {
const key = `rate:${ip}`;
const count = await redis.incr(key);
if (count === 1) {
await redis.expire(key, 60); // 60s 过期
}
return count > 10; // 限制 10 次请求/分钟
};
app.get("/api/data", async (req, res) => {
if (await rateLimit(req.ip)) {
return res.status(429).send("请求过多,请稍后重试");
}
res.send("数据返回成功");
});
效果
- 同一 IP 每分钟最多 10 次请求
- 超出限制返回
429 Too Many Requests
六、总结
功能 | 实现方式 |
---|---|
缓存查询 | redis.get() / redis.setex() |
Session 存储 | connect-redis |
分布式锁 | SETNX + EX |
API 限流 | INCR + EXPIRE |
数据淘汰 | TTL + LRU |
连接优化 | ioredis 连接池 |
本篇文章介绍了 Node.js + Redis 在 缓存、会话存储、分布式锁、限流 等方面的应用,并提供了大量高质量代码。希望对你的高并发系统开发有所帮助!🚀