本地缓存

性能瓶颈的再思考

分片计数方案上线后,系统性能提升了很多。

但我发现了一个有趣的现象:

监控数据:

热门文章(前 100 篇):
- 访问量:占总访问的 80%
- Redis QPS:约 5000
- 响应时间:平均 5ms

普通文章:
- 访问量:占总访问的 20%
- Redis QPS:约 1000
- 响应时间:平均 8ms

热门文章的访问太频繁了!

虽然 Redis 很快,但:

  • 每次请求都要网络往返
  • 网络延迟至少 1-2ms
  • 高峰期网络可能拥堵

能否再优化?

我想到了本地缓存

本地缓存原理

传统方案:
用户请求 → 应用服务器 → Redis(网络往返)

本地缓存方案:
用户请求 → 应用服务器(本地内存)→ 命中则返回

      未命中 → Redis(网络往返)

优势:

  • 本地读取速度极快(纳秒级)
  • 减少 Redis 压力
  • 降低网络延迟

劣势:

  • 数据可能不一致
  • 占用应用服务器内存
  • 需要处理缓存失效

实现方案

方案 1:简单内存缓存

点赞计数本地缓存

方案 2:LRU 缓存

方案 3:多级缓存

缓存一致性

问题:多实例缓存不一致

场景:多个应用服务器

服务器 A:
- 本地缓存:article:123:like_count = 100

服务器 B:
- 本地缓存:article:123:like_count = 100

用户点赞(请求到达服务器 A):
- 服务器 A:更新 Redis → 101
- 服务器 A:更新本地缓存 → 101
- 服务器 B:本地缓存仍是 100(旧数据)

结果:不同服务器返回不同的值

解决方案 1:短 TTL

解决方案 2:主动失效

解决方案 3:版本号

性能对比

测试代码

实际效果

监控数据

本地缓存上线后:

热门文章访问:
- 本地缓存命中率:95%
- Redis QPS:从 5000 降到 250
- 响应时间:从 5ms 降到 0.1ms

应用服务器:
- CPU:从 45% 降到 20%
- 内存:增加约 100MB(可接受)

用户体验:
- 页面加载更快
- 点赞响应更流畅

适用场景

适合使用本地缓存的场景:
1. 热点数据(访问频繁)
2. 可容忍短暂不一致
3. 读多写少
4. 数据量不大

不适合使用本地缓存的场景:
1. 数据实时性要求高
2. 数据量大(内存有限)
3. 频繁更新
4. 需要强一致性

课后练习

练习 1

本地缓存和 Redis 缓存有什么区别?如何选择?

参考答案(3 个标签)
缓存架构设计性能

对比:

特性本地缓存Redis 缓存
读取速度极快(纳秒级)快(微秒级)
容量受应用服务器内存限制可扩展(集群)
一致性多实例不一致全局一致
网络开销
适用数据热点数据通用数据

选择建议:

使用本地缓存:
- 热点数据(如热门文章)
- 配置数据
- 不变数据
- 读多写少

使用 Redis 缓存:
- 通用数据
- 需要全局一致
- 数据量大
- 频繁更新

练习 2

如何实现本地缓存的”预热”?

参考答案(3 个标签)
缓存预热性能优化

预热方案:

练习 3

本地缓存如何实现”防雪崩”?

参考答案(3 个标签)
缓存雪崩高可用

防雪崩方案:

练习 4

如何监控本地缓存的命中率?

参考答案(3 个标签)
监控缓存性能指标

监控方案:

练习 5

多实例环境下,如何保证本地缓存的一致性?

参考答案(3 个标签)
分布式缓存一致性架构

方案对比:

方案实现复杂度一致性性能
短 TTL最终一致
Pub/Sub最终一致
版本号最终一致
定期刷新最终一致

推荐:短 TTL + Pub/Sub

思考题

  1. 本地缓存会占用应用服务器内存,如何控制内存使用?

  2. 如果本地缓存和 Redis 数据不一致,如何处理?

  3. 如何实现本地缓存的”按需加载”?

💡 提示:这些问题没有标准答案,建议结合实际情况深入思考。