暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

用了缓存还是慢?数据库压力不减的真正原因

解压泡泡糖 2025-05-04
137

很多人以为“加了缓存,性能就一定好”,结果上线之后,系统依然慢,数据库 QPS 居高不下,Redis 明明命中率 80%,数据库却一点没减压。

为什么用了缓存,数据库还是这么忙?问题根本不在“有没有缓存”,而在“你怎么用的缓存”。

一、缓存用了,为什么数据库还慢?

1. 热点数据命中高,长尾请求依然打库

缓存往往只能命中频率高的数据,比如用户信息、商品详情。但很多业务请求带有动态查询条件,比如搜索、筛选、分页——这些基本都要打数据库。

数据库压力其实主要来源于这类“非缓存型请求”。

2. 缓存粒度不对,重复命中价值不高

有的缓存把整个页面缓存,有的把字段拆得太细,导致缓存本身存在但复用效率低。真正能“扛住压力”的缓存,是要有高命中率 + 高请求价值的。

3. 缓存更新策略设计不合理

写入数据后不刷新缓存,导致“写库-读缓存”数据不一致,最终只能频繁回源查库。

  • 最常见的错法:只做读缓存,不做写更新或延迟更新

  • 正确姿势:更新数据库的同时也更新/删除缓存

4. 缓存穿透、雪崩、击穿没有防护

这些是缓存的三大“杀手”:

  • 穿透:大量查询无效数据,缓存没存,数据库压力全背

  • 击穿:某热点缓存突然过期,成千上万请求同时打数据库

  • 雪崩:大量缓存同时失效,系统直接崩溃

二、如何正确使用缓存降低数据库压力?

1. 加布隆过滤器,拦住无效请求

比如用户 ID、商品 ID 可以先用布隆过滤器判断是否合法,不合法的直接拦截,别让它打到数据库。

2. 加互斥锁,防止击穿

热点数据失效时,用互斥锁保护回源操作,只让第一个请求去查库并刷新缓存

if redis.get(key) is None:    if acquire_lock(key):        data = query_db()        redis.set(key, data)

3. 设置不同过期时间,避免雪崩

批量缓存时,随机设置 TTL,比如设置为 300s ~ 600s 之间,错开失效时间。

4. 使用异步缓存更新机制

对数据变动频繁、读写比低的业务,可以考虑定时批量刷新缓存,而不是每次操作都实时更新。

三、总结

缓存不是“加了就快”的灵丹妙药,真正的优化效果来自:

  • 命中率高

  • 更新策略合理

  • 防击穿防雪崩机制完备

不是数据库撑不住,而是你根本没把缓存用明白。

文章转载自解压泡泡糖,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论