如何使用Micrometer正确记录TTL指标?应选counter、timer还是gauge?
使用Micrometer记录缓存TTL指标的正确方式
先明确三个核心指标的适用边界
- Counter:仅用于计数(只增不减),适合统计缓存命中次数、过期次数这类频次数据,完全不适合时长类指标。
- Timer:用于统计时间值的分布情况,比如平均值、百分位数(P95/P99),适合记录单次缓存命中时的时长数据。
- Gauge:用于统计瞬时状态值(可增可减),适合反映缓存整体的TTL状态。
针对你的场景的具体选择
1. 记录缓存条目「已存放时长」
如果想分析每次命中缓存时,条目已存活时长的分布规律(比如95%的命中条目存活了多久),用Timer。
每次命中缓存时,计算当前时间与条目创建时间的差值,将这个时长传入Timer:
// 假设缓存条目有createTime字段 long aliveDuration = System.currentTimeMillis() - cacheEntry.getCreateTime(); Metrics.timer("cache.entry.alive.duration") .record(aliveDuration, TimeUnit.MILLISECONDS);
2. 记录缓存条目「距离过期的时长」
分两种情况:
- 若要统计单次命中时剩余TTL的分布(比如大部分命中的条目还剩多久过期),同样用Timer,逻辑和上面类似,只是计算的是过期时间与当前时间的差值:
long remainingTtl = cacheEntry.getExpireTime() - System.currentTimeMillis(); Metrics.timer("cache.entry.remaining.ttl") .record(remainingTtl, TimeUnit.MILLISECONDS); - 若要监控缓存整体的剩余TTL状态(比如当前所有缓存条目的平均剩余TTL、最大剩余TTL),用Gauge。需要实现一个逻辑来获取聚合后的瞬时值,比如:
注意:Gauge的取值逻辑要尽量轻量,避免遍历大量缓存条目导致性能问题,建议抽样或维护预计算的聚合值。Metrics.gauge("cache.avg.remaining.ttl", this, () -> cache.getAllEntries().stream() .mapToLong(entry -> entry.getExpireTime() - System.currentTimeMillis()) .average() .orElse(0));
总结
- 单次命中时的时长分布(已存活/剩余TTL)→ Timer
- 缓存整体的瞬时TTL状态 → Gauge
- Counter只用来统计频次类数据(比如
cache.hits.count、cache.expirations.count)
内容的提问来源于stack exchange,提问作者Bennett Lynch
相关产品推荐
相关产品推荐

