639 字
3 分钟
Redis 高性能缓存实战:缓存策略、分布式锁与性能优化的完全指南
Redis 高性能缓存实战:缓存策略、分布式锁与性能优化的完全指南
⚡ 前言:Redis 是当今最流行的内存数据结构存储系统,它不仅可以作为缓存使用,还可以实现消息队列、排行榜、实时统计等多种功能。
一、Redis 数据类型实战
1.1 String 类型
// 缓存对象const user = { id: 1, name: '张三' };await client.set('user:1', JSON.stringify(user));await client.expire('user:1', 3600);
// 原子计数器await client.incr('page:views:home');await client.incrBy('user:1:credits', 100);
// 分布式锁const lockKey = 'lock:order:123';const token = Date.now().toString();const acquired = await client.set(lockKey, token, { NX: true, EX: 30});1.2 Hash 类型
// 存储用户资料await client.hSet('user:1:profile', { name: '张三', email: 'zhangsan@example.com'});
// 购物车await client.hSet('cart:user:1', { 'product:1001': '2', 'product:1002': '1'});1.3 List 类型
// 消息队列await client.lPush('queue:emails', JSON.stringify(message));const result = await client.brPop('queue:emails', 0);
// 最近访问记录await client.lPush('user:1:history', '/products/123');await client.lTrim('user:1:history', 0, 99);1.4 Sorted Set
// 排行榜await client.zAdd('leaderboard:game1', [ { score: 1000, value: 'player:1' }, { score: 1200, value: 'player:2' }]);
const top10 = await client.zRevRangeWithScores('leaderboard:game1', 0, 9);二、缓存设计模式
2.1 Cache-Aside
class CacheAside { async get(key) { const cached = await redis.get(`cache:${key}`); if (cached) return JSON.parse(cached);
const data = await db.get(key); if (data) { await redis.setEx(`cache:${key}`, 3600, JSON.stringify(data)); } return data; }}2.2 缓存穿透解决方案
async function getWithNullCache(key) { const cached = await redis.get(`cache:${key}`); if (cached === 'null') return null; if (cached) return JSON.parse(cached);
const data = await db.get(key); await redis.setEx( `cache:${key}`, data ? 3600 : 60, JSON.stringify(data) ); return data;}三、分布式锁
3.1 Redlock 算法
const Redlock = require('redlock');const redlock = new Redlock([client]);
async function withLock(resource, ttl, callback) { const lock = await redlock.acquire([resource], ttl); try { return await callback(); } finally { await lock.release(); }}四、性能优化
4.1 Pipeline
const pipeline = client.multi();for (let i = 0; i < 1000; i++) { pipeline.set(`key:${i}`, `value:${i}`);}await pipeline.exec();4.2 大 Key 处理
async function splitBigHash(bigKey, chunkSize = 1000) { const data = await client.hGetAll(bigKey); const entries = Object.entries(data);
for (let i = 0; i < entries.length; i += chunkSize) { const chunk = entries.slice(i, i + chunkSize); const newKey = `${bigKey}:chunk:${i / chunkSize}`; await client.hSet(newKey, Object.fromEntries(chunk)); }
await client.del(bigKey);}五、实战案例
5.1 秒杀系统
async function seckill(activityId, skuId, userId) { const stockKey = `seckill:stock:${activityId}:${skuId}`; const userKey = `seckill:user:${activityId}:${userId}`;
const hasBought = await redis.get(userKey); if (hasBought) return { success: false, message: '已参与' };
const script = ` local stock = tonumber(redis.call('get', KEYS[1])); if stock == nil or stock <= 0 then return -1; end redis.call('decr', KEYS[1]); redis.call('set', KEYS[2], '1', 'EX', 86400); return stock - 1; `;
const remaining = await redis.eval(script, 2, stockKey, userKey); if (remaining < 0) return { success: false, message: '库存不足' };
await createOrder(activityId, skuId, userId); return { success: true, remaining };}六、总结
Redis 应用场景总结:
- 数据类型选择:根据场景选择合适的数据结构
- 缓存设计:理解 Cache-Aside 等模式
- 分布式锁:保证分布式环境数据一致性
- 性能优化:Pipeline、大 Key 处理
- 实战应用:秒杀、排行榜、实时统计
希望这篇文章能帮助你更好地使用 Redis!
Redis 高性能缓存实战:缓存策略、分布式锁与性能优化的完全指南
https://www.oferry.com/posts/a80/