redis击穿导致慢sql的链路特征是同一sql在极短时间内被高频重复执行,表现为链路追踪中该db调用节点出现“尖峰式密集毛刺”,qps暴涨、连接池打满、后续请求排队,真正瓶颈常为连接等待时间或线程阻塞而非sql执行耗时。

Redis击穿导致慢SQL的链路特征是什么?
Redis击穿本身不直接产生慢SQL,但会引发大量并发请求绕过缓存直查数据库——此时慢SQL不是单条变慢,而是**同一SQL在极短时间内被高频重复执行**,表现为链路追踪中该DB调用节点出现“尖峰式密集毛刺”,且每个调用耗时未必超标(比如都在200ms内),但整体QPS暴涨、连接池打满、后续请求排队。真正拖垮系统的往往是连接等待时间(wait_time)或线程阻塞,而非SQL执行本身。
如何在Jaeger/SkyWalking里快速定位这类问题?
不能只看单个Span的duration,要组合三个维度过滤:
- 按服务名 + 操作名筛选出所有
db.query或mysql.select类型的Span - 叠加时间窗口:选击穿发生前后的5分钟,避免被日常流量淹没
- 按
tags.db.statement聚合,找“相同SQL文本出现频次突增>3倍”的Top 3
如果用SkyWalking,可直接在「DB监控」页点击「慢SQL排行」旁的「异常调用趋势」按钮,它会自动标出同比激增的语句;Jaeger则需在Search页手动加Filter:db.statement:"SELECT * FROM user WHERE id = ?" AND duration > 100ms,再切到Graph视图观察调用密度。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
为什么链路追踪常漏掉真正的瓶颈?
因为击穿引发的慢SQL往往伴随两个隐藏现象,而默认采样策略会丢弃它们:
-
wait_time(连接池等待)不在Span的duration里体现,它属于前置阶段,需额外采集jdbc.connection.wait.time等自定义Tag - 大量请求在获取连接失败后直接返回500或超时,根本没走到DB Span,这些“空洞请求”在链路里是断开的,但日志里会出现
CannotGetJdbcConnectionException - 采样率设为固定值(如1%)时,高频但单次快的SQL调用大概率被跳过,建议对
db.type=mysql开启强制采样:if duration > 50ms or count_per_second > 10 then sample=100%
怎么把缓存层和DB层的调用串成一条完整链路?
关键不是加更多Span,而是统一TraceID透传和关键状态标记:
- 在缓存查询逻辑里,无论命中/未命中,都写入
cache.hit: true/false到当前Span的Tag中 - 当
cache.hit=false时,强制在后续DB Span里添加cache.miss_reason: "redis_expired",方便后续按原因聚合 - 避免在
catch块里新建Span——比如Redis连接失败后降级查DB,必须复用原始TraceID,否则链路断裂
最容易被忽略的是:很多SDK默认不会把Redis操作本身作为独立Span上报(尤其Jedis),需要显式启用spring.sleuth.redis.enabled=true或手动包装JedisPool,否则你永远不知道缓存层是否真的挂了,还是只是“查了但没返回”。










