上一篇
去年双十一大促期间,某电商平台的商品详情页接口突然响应缓慢,数据库CPU直接飙到95%!😱 运维团队紧急排查发现,同一个商品基础信息SQL在高峰期被重复执行了每秒8000次——这就像让MySQL不停地回答同一个问题,而它每次都要翻箱倒柜找答案。
SELECT * FROM products WHERE item_id = 12345;
这种场景下,查询缓存就像给MySQL配了个"记忆小秘书"🧠,今天我们就来实战如何用缓存机制为数据库"减负"!
MySQL自带的查询缓存(Query Cache)会把:
-- 查看查询缓存状态(MySQL 5.7及之前版本) SHOW VARIABLES LIKE 'query_cache%';
-- 在my.cnf中配置示例 query_cache_type = 1 -- 启用缓存 query_cache_size = 64M -- 分配内存大小 query_cache_limit = 2M -- 单条结果最大缓存
⚠️ 注意:MySQL 8.0已移除该功能,但5.7及以下版本仍可用
当查询缓存不适用时,可以用Redis作为前置缓存:
# Python伪代码示例 def get_product_info(item_id): # 先查Redis cache_key = f"product:{item_id}" data = redis.get(cache_key) if not data: # 缓存未命中则查数据库 data = db.execute("SELECT * FROM products WHERE item_id = %s", item_id) # 写入Redis并设置5分钟过期 redis.setex(cache_key, 300, data) return data
策略 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
定时刷新 | 实现简单 | 实时性差 | 不常变的数据 |
延迟双删 | 强一致性 | 实现复杂 | 金融交易类 |
异步更新 | 性能最优 | 可能短暂不一致 |
用户请求 → CDN缓存 → Nginx缓存 → 应用Redis缓存 → MySQL
通过监控提前发现热点商品:
-- 找出最近1小时最热商品 SELECT item_id, COUNT(*) as query_count FROM product_access_log WHERE access_time > NOW() - INTERVAL 1 HOUR GROUP BY item_id ORDER BY query_count DESC LIMIT 100;
# 随机过期时间避免集体失效 expire_time = 300 + random.randint(0, 60) # 5-6分钟随机 redis.setex(cache_key, expire_time, data)
缓存穿透防护:对不存在的key也做短暂缓存
if data is None: # 数据库也不存在 redis.setex(cache_key, 60, "NULL") # 缓存空值1分钟
批量查询优化:
# 不好的做法:循环查Redis for id in item_ids: redis.get(f"product:{id}") # 好的做法:批量查询 redis.mget([f"product:{id}" for id in item_ids])
大Value拆分:超过1MB的数据考虑分片存储
某电商平台优化后数据:
│ 指标 │ 优化前 │ 优化后 │
├──────────────┼─────────┼─────────┤
│ QPS峰值 │ 12,000 │ 38,000 │
│ 平均响应时间 │ 450ms │ 120ms │
│ MySQL CPU │ 92% │ 65% │
缓存就像给数据库请了个"记忆大师"👨🎓,但要注意:
下次当你看到数据库在"喘粗气"时,不妨问问:这个查询结果能不能暂时记住?🤔 最好的优化往往是让请求根本到不了数据库!
本文由 操鹏煊 于2025-08-07发表在【云服务器提供商】,文中图片由(操鹏煊)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://up.7tqx.com/wenda/561217.html
发表评论