返回首页
⚙️ 后端 / 架构
Redis 8 实战:从入门到生产级缓存架构完整指南
Redis 8 是 2026 年最流行的 KV 存储。本文从 0 到生产级缓存架构,含 6 大核心场景 + 性能优化 + 集群 + 高可用 + 与 AI Agent 集成。
Redis · 缓存 · 分布式 · Session · 排行榜 · 限流 · 分布式锁
📰
今日技术简讯
📰 技术简讯 · 2026-08-04
今日聚合 6 条热门技术内容(中文素材优先)。
🤖 AI / LLM
1. Redis 8 GA 推出 AGENTS 模块
- 链接:https://redis.io/blog/redis-8-ga
- 来源:Redis
- 摘要:Redis 8 GA 推出 AGENTS 模块(AI Agent 原生支持)+ 向量搜索 + 许可证回归 BSD。
2. Valkey 8 兼容 Redis 8
- 链接:https://valkey.io/blog/8
- 来源:Valkey
- 摘要:Valkey 8 完全兼容 Redis 8 API,Linux Foundation 治理,BSD 许可证。
🎨 前端 / Web
3. Upstash Redis 推出 HTTP/3
- 链接:https://upstash.com/blog/http3
- 来源:Upstash
- 摘要:Upstash Redis 推出 HTTP/3,全球边缘节点 P99 < 50ms。
⚙️ 后端 / 架构
4. Dragonfly 推出多线程 Redis
- 链接:https://dragonflydb.io/blog/multithread
- 来源:Dragonfly
- 摘要:Dragonfly 推出多线程 Redis 兼容服务,QPS 提升 25x(vs 单线程 Redis)。
5. KeyDB 推出生产级集群
- 链接:https://github.com/snap-stanford/KeyDB
- 来源:Snap
- 摘要:KeyDB 推出生产级集群,多主架构,零停机升级。
🚀 独立开发 / OPC
6. 即刻"Redis 缓存架构"专题
- 链接:https://m.okjike.com/redis-2026
- 来源:即刻
- 摘要:即刻 200+ 独立开发者分享 Redis 缓存架构,Session / 排行榜 / 限流 / 分布式锁实战。
数据来源:掘金 / InfoQ 中文 / 即刻 / 少数派 / HN 采集时间:2026-08-04 09:00 (UTC+8)
📝
今日深度文
Redis 8 实战:从入门到生产级缓存架构完整指南
一句话结论:Redis 8 = 内存数据库的"瑞士军刀"。缓存 / Session / 排行榜 / 限流 / 分布式锁 / AI Agent(AGENTS 模块)。本文从 0 到生产级缓存架构。
背景
2026 年 Redis 生态:
Redis 8(2026-05 GA)
├─ 许可证回归 BSD(社区版)
├─ AGENTS 模块(AI Agent 原生支持)
├─ 向量搜索(RedisVL)
├─ JSON / Search / Timeseries
└─ 100% 向后兼容
替代方案:
├─ Valkey 8(Linux Foundation,BSD)
├─ Dragonfly(多线程,25x)
└─ KeyDB(多主)
为什么 Redis 仍是首选:
- 极致性能:QPS 100K+(单实例)
- 数据结构丰富:String / Hash / List / Set / Sorted Set / Stream
- 持久化:RDB / AOF
- 集群:Redis Cluster(水平扩展)
- 生态成熟:所有云厂商 / 框架都支持
6 大核心场景
场景 1:缓存(最常用)
// lib/cache.ts
import { Redis } from 'ioredis';
const redis = new Redis(process.env.REDIS_URL!);
export async function cached<T>(
key: string,
ttl: number,
fetcher: () => Promise<T>
): Promise<T> {
// 1. 读缓存
const cached = await redis.get(key);
if (cached) {
return JSON.parse(cached);
}
// 2. 回源
const data = await fetcher();
// 3. 写缓存
await redis.setex(key, ttl, JSON.stringify(data));
return data;
}
// 使用
const user = await cached(
`user:${userId}`,
300, // 5 分钟
() => db.user.findUnique({ where: { id: userId } })
);
场景 2:Session
// lib/session.ts
import { Redis } from 'ioredis';
const redis = new Redis(process.env.REDIS_URL!);
interface Session {
userId: string;
expiresAt: number;
}
export async function createSession(userId: string): Promise<string> {
const token = crypto.randomUUID();
const session: Session = {
userId,
expiresAt: Date.now() + 30 * 24 * 60 * 60 * 1000, // 30 天
};
await redis.setex(
`session:${token}`,
30 * 24 * 60 * 60,
JSON.stringify(session)
);
return token;
}
export async function getSession(token: string): Promise<Session | null> {
const data = await redis.get(`session:${token}`);
if (!data) return null;
const session = JSON.parse(data);
if (Date.now() > session.expiresAt) {
await redis.del(`session:${token}`);
return null;
}
return session;
}
场景 3:排行榜(Sorted Set)
// lib/leaderboard.ts
import { Redis } from 'ioredis';
const redis = new Redis(process.env.REDIS_URL!);
// 增加分数
await redis.zadd('leaderboard:global', Date.now(), `user:${userId}`);
// Top 10
const top10 = await redis.zrevrange('leaderboard:global', 0, 9, 'WITHSCORES');
// 用户排名(升序,0 开始)
const rank = await redis.zrevrank('leaderboard:global', `user:${userId}`);
// 用户分数
const score = await redis.zscore('leaderboard:global', `user:${userId}`);
// Top N(with 用户信息)
const topWithInfo = await redis.zrevrange(
'leaderboard:global',
0,
99,
'WITHSCORES'
);
场景 4:限流
// lib/rate-limit.ts
import { Redis } from 'ioredis';
const redis = new Redis(process.env.REDIS_URL!);
// 滑动窗口限流
export async function rateLimit(
key: string,
limit: number,
window: number // 秒
): Promise<{ allowed: boolean; remaining: number; resetAt: number }> {
const now = Date.now();
const windowMs = window * 1000;
// 移除过期的请求
await redis.zremrangebyscore(key, 0, now - windowMs);
// 当前窗口内的请求数
const count = await redis.zcard(key);
if (count >= limit) {
const oldest = await redis.zrange(key, 0, 0, 'WITHSCORES');
const resetAt = Number(oldest[1]) + windowMs;
return { allowed: false, remaining: 0, resetAt };
}
// 添加当前请求
await redis.zadd(key, now, `${now}-${Math.random()}`);
await redis.expire(key, window);
return {
allowed: true,
remaining: limit - count - 1,
resetAt: now + windowMs,
};
}
// 使用:每分钟最多 60 次
const result = await rateLimit(`api:${userId}`, 60, 60);
if (!result.allowed) {
return new Response('Too Many Requests', { status: 429 });
}
场景 5:分布式锁
// lib/lock.ts
import { Redis } from 'ioredis';
const redis = new Redis(process.env.REDIS_URL!);
export async function acquireLock(
key: string,
ttl: number = 10000 // 10 秒
): Promise<string | null> {
const token = crypto.randomUUID();
// SET key token NX PX ttl
// NX: 不存在才设置
// PX: 毫秒级过期
const result = await redis.set(
`lock:${key}`,
token,
'PX',
ttl,
'NX'
);
return result === 'OK' ? token : null;
}
export async function releaseLock(key: string, token: string): Promise<boolean> {
// Lua 脚本保证原子性
const lua = `
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
end
`;
const result = await redis.eval(lua, 1, `lock:${key}`, token);
return result === 1;
}
// 使用:支付场景
async function processPayment(orderId: string) {
const lock = await acquireLock(`payment:${orderId}`, 30000);
if (!lock) {
throw new Error('Order is being processed');
}
try {
// 处理支付(唯一执行)
await chargeCustomer(orderId);
await markOrderPaid(orderId);
} finally {
await releaseLock(`payment:${orderId}`, lock);
}
}
场景 6:AI Agent(Redis 8 AGENTS)
// AI Agent 状态管理
import { Redis } from 'ioredis';
const redis = new Redis(process.env.REDIS_URL!);
// Agent 状态(关联 7/11 LangGraph)
class AgentState {
async save(threadId: string, state: any) {
await redis.json.set(`agent:${threadId}`, '$', state);
await redis.expire(`agent:${threadId}`, 3600);
}
async load(threadId: string): Promise<any | null> {
const state = await redis.json.get(`agent:${threadId}`);
return state;
}
}
// 向量搜索(关联 7/15 RAG)
class VectorStore {
async add(id: string, embedding: number[], metadata: any) {
// VECTOR 字段 + JSON metadata
await redis.call(
'JSON.SET',
`vec:${id}`,
'$',
JSON.stringify({ embedding, metadata })
);
}
async search(query: number[], topK: number = 5) {
// 用 FT.SEARCH 做 KNN 搜索
const result = await redis.call(
'FT.SEARCH',
'idx:embeddings',
'*=>[KNN 5 @embedding $vec AS score]',
'PARAMS', '2', 'vec', Buffer.from(new Float32Array(query).buffer),
'SORTBY', 'score', 'ASC'
);
return result;
}
}
5 个实战项目
项目 1:用户认证(Session)
// middleware/auth.ts
import { NextResponse } from 'next/server';
import { getSession } from '@/lib/session';
export async function middleware(request: Request) {
const token = request.headers.get('cookie')?.match(/token=([^;]+)/)?.[1];
if (!token) {
return NextResponse.redirect('/login');
}
const session = await getSession(token);
if (!session) {
return NextResponse.redirect('/login');
}
return NextResponse.next();
}
项目 2:电商秒杀
// 秒杀(100 个库存,10000 人抢)
async function seckill(productId: string, userId: string) {
const stockKey = `seckill:stock:${productId}`;
const userKey = `seckill:user:${productId}`;
// 1. 防重复购买
const alreadyBought = await redis.sismember(userKey, userId);
if (alreadyBought) {
return { success: false, reason: 'already_bought' };
}
// 2. 原子扣减库存(Lua 脚本)
const lua = `
local stock = tonumber(redis.call('get', KEYS[1]))
if stock <= 0 then
return 0
end
redis.call('decr', KEYS[1])
redis.call('sadd', KEYS[2], ARGV[1])
return 1
`;
const result = await redis.eval(
lua,
2,
stockKey,
userKey,
userId
);
if (result === 0) {
return { success: false, reason: 'out_of_stock' };
}
// 3. 创建订单
await db.order.create({
data: { productId, userId, status: 'pending' },
});
return { success: true };
}
项目 3:实时通知
// 用 Stream 实现消息队列(关联 7/27 GitHub Actions)
import { Redis } from 'ioredis';
const redis = new Redis(process.env.REDIS_URL!);
// 生产者
async function publishNotification(userId: string, message: any) {
await redis.xadd(
`notifications:${userId}`,
'*',
'type', message.type,
'title', message.title,
'content', message.content,
'createdAt', Date.now().toString()
);
}
// 消费者
async function consumeNotifications(userId: string) {
while (true) {
const result = await redis.xread(
'BLOCK', 0,
'STREAMS', `notifications:${userId}`, '$'
);
if (result) {
for (const [stream, messages] of result) {
for (const [id, fields] of messages) {
// 推送到客户端
await sendToClient(userId, { id, ...fields });
}
}
}
}
}
项目 4:分布式 ID 生成
// 类雪花算法(基于 Redis)
async function generateId(): Promise<string> {
const key = 'id:generator';
const lua = `
local seq = redis.call('incr', KEYS[1])
local timestamp = tonumber(ARGV[1])
return timestamp * 10000 + (seq % 10000)
`;
const timestamp = Date.now() - new Date('2026-01-01').getTime();
const id = await redis.eval(lua, 1, key, timestamp);
// 重置(每秒)
await redis.expire(key, 1);
return id.toString();
}
项目 5:内容推荐
// 协同过滤(基于 Sorted Set)
async function getRecommendations(userId: string) {
// 1. 用户看过的内容
const viewed = await redis.zrange(`user:viewed:${userId}`, 0, -1);
// 2. 找相似用户(看过的交集)
const similarUsers = await redis.zinter(
`user:viewed:${userId}`,
'user:viewed:*'
);
// 3. 提取相似用户看过的内容(推荐)
const recommendations = await redis.zunion(
...similarUsers.map(u => `user:viewed:${u}`)
);
// 4. 排除已看
return recommendations.filter(item => !viewed.includes(item));
}
性能优化 10 招
1. Pipeline(批量操作)
// ❌ 100 次单条请求 = 100ms 网络
for (const key of keys) {
await redis.get(key);
}
// ✅ 1 次 pipeline = 5ms
const results = await redis.pipeline()
...keys.map(key => redis.get(key))
.exec();
2. Lua 脚本(原子操作)
// ✅ 复杂逻辑用 Lua(原子 + 减少网络)
const lua = `
local stock = tonumber(redis.call('get', KEYS[1]))
if stock > 0 then
redis.call('decr', KEYS[1])
return 1
end
return 0
`;
const success = await redis.eval(lua, 1, 'stock:1');
3. Hash 代替多个 String
// ❌ 100 个 String
await redis.set('user:1:name', 'Alice');
await redis.set('user:1:email', 'alice@example.com');
await redis.set('user:1:age', '30');
// ✅ 1 个 Hash
await redis.hset('user:1', {
name: 'Alice',
email: 'alice@example.com',
age: 30,
});
4. 选择合适数据结构
String: 缓存单个值
Hash: 对象
List: 队列 / 最新 N 个
Set: 去重 / 共同好友
Sorted Set: 排行榜 / 范围查询
Stream: 消息流
JSON: 复杂对象
Vector: 向量搜索(Redis 8)
5. 避免大 Key
❌ key 包含 100 万个元素
✅ 拆分 key(user:1:items:0, user:1:items:1)
6. 避免热点 Key
❌ 100 万请求打同一个 key
✅ 加随机后缀(key:1, key:2, ...)
7. 设置合理 TTL
// ✅ 必须设置 TTL(防止内存爆炸)
await redis.setex('key', 3600, 'value');
// ✅ 永久 key 也要设置(清理)
await redis.set('key', 'value', 'EX', 86400);
8. 内存优化
# redis.conf
maxmemory 4gb
maxmemory-policy allkeys-lru # 内存满时淘汰最近最少使用
9. 持久化策略
# RDB(快照)
save 900 1 # 900 秒至少 1 个 key 变化
save 300 10 # 300 秒至少 10 个 key 变化
# AOF(日志)
appendonly yes
appendfsync everysec # 每秒 fsync
10. 监控指标
// 关键指标
- used_memory
- used_memory_peak
- connected_clients
- total_commands_processed
- keyspace_hits / keyspace_misses(缓存命中率)
Redis Cluster 集群
6 节点(3 主 3 从)
├─ 16384 哈希槽
├─ 水平扩展(最多 1000 节点)
├─ 自动故障转移
└─ 客户端分片(无需 proxy)
// ioredis cluster
const cluster = new Redis.Cluster([
{ host: 'redis-1', port: 6379 },
{ host: 'redis-2', port: 6379 },
{ host: 'redis-3', port: 6379 },
], {
redisOptions: {
password: process.env.REDIS_PASSWORD,
},
scaleReads: 'slave', // 从从节点读
});
5 个常见坑
坑 1:无 TTL
❌ set 'key' 'value' (永不过期 → 内存爆炸)
✅ setex 'key' 3600 'value'
坑 2:雪崩
// ❌ 所有 key 同时过期 → DB 雪崩
for (const key of keys) {
await redis.setex(key, 3600, value);
}
// ✅ 加随机 TTL(防雪崩)
for (const key of keys) {
const ttl = 3600 + Math.random() * 600;
await redis.setex(key, ttl, value);
}
坑 3:穿透
// ❌ 不存在的 key 每次都查 DB
const data = await redis.get(key);
if (!data) {
return await db.query(); // 每次都打 DB
}
// ✅ 缓存空值
const data = await redis.get(key);
if (data === null) {
const dbData = await db.query();
if (!dbData) {
await redis.setex(key, 60, 'null'); // 缓存空值 60 秒
}
return dbData;
}
坑 4:击穿
// ❌ 热点 key 过期瞬间,所有请求打 DB
const data = await redis.get('hot:key');
if (!data) return await db.query();
// ✅ 分布式锁(防止击穿)
const lock = await acquireLock('hot:key');
if (lock) {
const data = await db.query();
await redis.setex('hot:key', 3600, JSON.stringify(data));
await releaseLock('hot:key', lock);
}
坑 5:误用 List 当队列
// ❌ 用 List 当消息队列(无消费者组)
await redis.lpush('queue', msg);
await redis.brpop('queue', 0);
// ✅ 用 Stream(有消费者组 + ACK)
await redis.xadd('mystream', '*', 'data', JSON.stringify(msg));
await redis.xreadgroup('GROUP', 'g1', 'c1', '>', 'STREAMS', 'mystream', '>');
与之前内容的关系
7/15 RAG + pgvector → 向量搜索
7/21 PostgreSQL 18 → 关系数据库
7/26 Cloudflare D1 → 边缘 SQLite
7/29 WebGPU → 浏览器 AI
8/1 LLM 工程化 → AI 状态
8/4 Redis 8 → 缓存 / 内存数据库 ← 今天
→ "持久化 → 缓存"完整数据层
7 天落地路径
Day 1:安装 Redis
# Docker
docker run -d --name redis -p 6379:6379 redis:8
# macOS
brew install redis
redis-server
Day 2:基础命令
$ redis-cli
> SET key value EX 60
> GET key
> HSET user:1 name "Alice"
> ZADD leaderboard 100 user:1
Day 3:应用集成
import { Redis } from 'ioredis';
const redis = new Redis(process.env.REDIS_URL);
Day 4:缓存模式
// cache-aside / read-through / write-through
Day 5:高级特性
// Stream / Pub-Sub / Pipeline / Lua
Day 6:集群
// 6 节点集群 + 客户端分片
Day 7:监控
# Prometheus + Grafana
# Redis Exporter
我的看法
Redis 8 是 2026 年内存数据库的"瑞士军刀":
- 极致性能:100K QPS
- 数据结构丰富:10+ 种
- AI 原生:AGENTS 模块
- 开源回归:BSD 许可证
- 生态成熟:所有云厂商支持
对独立开发者的建议:
- 缓存必装:替代 DB 80% 读请求
- Session 用 Redis:替代 JWT
- 排行榜首选:Sorted Set
- 限流必备:滑动窗口
- 分布式锁:秒杀 / 支付
参考
- Redis 官方
- Redis 8 Release Notes
- Valkey
- ioredis
- Upstash
- PostgreSQL(7/21)
- Workers + D1(7/26)
- LLMOps(8/1)
本文基于 Redis 8 GA(2026-05),8 月最新实战。