优化 Cache 缓存是一项系统工程,涉及硬件、操作系统、应用架构和代码实现等多个层面。优化的核心目标是:提高命中率(Hit Rate)、减少延迟(Latency)、控制成本。
以下是分层次的 Cache 优化指南:
不要只依赖一个缓存层,而是构建多级缓存体系:
functools.lru_cache。
优化建议: 结合使用。例如:先查本地缓存(JVM 堆内),如果没有再查 Redis,如果还没有再查数据库。但需警惕本地缓存导致的“读到旧数据”问题。
在系统启动或流量洪峰到来之前,提前将热点数据加载到缓存中。
这是最复杂的部分。数据更新后,缓存怎么办?
user:1001:profile 比 user_profile_information_for_user_id_1001 好。allkeys-lru: 淘汰最久未使用的 Key(最常用)。volatile-lru: 仅淘汰设置了过期时间的最久未使用 Key。allkeys-lfu: 淘汰使用频率最低的 Key(适合突发流量场景,比 LRU 更精准)。KEYS *,大范围的 SMEMBERS),使用 SCAN 代替。public User getUserById(Long id) {
String key = "user:" + id;
// 1. 查缓存
User user = redis.get(key);
if (user != null) {
return user;
}
// 2. 缓存未命中,加锁防止击穿
synchronized (this) { // 实际生产中建议用 Redis 分布式锁
// 双重检查
user = redis.get(key);
if (user != null) return user;
// 3. 查数据库
user = userDao.findById(id);
if (user != null) {
// 4. 写缓存,设置随机过期时间防止雪崩
redis.setex(key, user, 3600 + RandomUtil.randomInt(0, 300));
} else {
// 5. 缓存空值防止穿透
redis.setex(key, EMPTY_OBJ, 60);
}
}
return user;
}
如果不想加锁,可以使用逻辑过期:
class CacheData {
private Object data;
private long expireTime; // 逻辑过期时间
}
// 后台线程扫描过期数据并刷新,或者检查到过期时异步刷新
redis-cli --bigkeys 找出大 Key 并拆分。没有银弹,最好的优化是根据具体的业务场景(读多写少?数据一致性要求?)来权衡策略。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。