Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
public class RedisProCache extends RedisCache {

/**
* 指标写侧 seam — 6 个 metric 的注册 + null-safe 记录 + 快照读取全部收口在本字段。
* 指标写侧 seam — 7 个 metric 的注册 + null-safe 记录 + 快照读取全部收口在本字段。
*
* <p>{@code MeterRegistry} 缺失时本字段构造为空 registry(全部 6 字段为 null),record 方法全 no-op。
* <p>{@code MeterRegistry} 缺失时本字段构造为空 registry(全部 7 字段为 null),record 方法全 no-op。
*/
private final RedisProCacheMetricsRegistry metricsRegistry;

Expand Down Expand Up @@ -69,7 +69,7 @@ public class RedisProCache extends RedisCache {
*
* <p>构造期委派 3 个 deep seam:
* <ol>
* <li>{@link RedisProCacheMetricsRegistry} — 6 metric 注册</li>
* <li>{@link RedisProCacheMetricsRegistry} — 7 metric 注册</li>
* <li>{@link CacheOperationResolver} — operation 解析</li>
* <li>{@link LoaderOrchestrator} — loader 路径编排</li>
* </ol>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@
* <p><b>与 {@link CacheMetrics} 的对称性</b>:本 seam 是"写侧"(注册 + 记录),与读侧
* 快照({@link CacheMetrics})配对形成<em>指标领域</em> 完整边界。读侧只读、写侧只写 — 关注点分离。
*
* <p><b>与 {@link RedisProCacheTimers} 的关系</b>:{@link RedisProCacheTimers} 是 metric 原语
* helper({@code registerTimer} / {@code registerCounter} / {@code timed} / {@code timedGet} /
* {@code safeIncrement}),本身是工具类无状态。本类是 metric 集合的<em>容器</em>(6 字段 + 6
* 业务语义方法),把原语按"缓存实例"的语义组装起来。两层 seam 形成 composition — 删除任意
* 一层,复杂度上浮。
* <p>本类在 metric ownership seam 内部封装注册、自增与计时原语,并按缓存实例语义组装。
* record 方法复用这些私有 helper;recordPut/recordEvict 保留计时启用时将 operation counter
* 放在 finally 中的局部结构,以维持异常路径的计数语义。
*
* <p><b>公开方法(业务语义)</b>:
* <ul>
Expand All @@ -37,7 +35,7 @@
* <li>{@link #metrics()} — 返回当前 cache 实例的不可变指标快照</li>
* </ul>
*
* <p><b>null-safe 语义</b>:{@link MeterRegistry} 为 null 时(即未启用指标),全部 6 个内部
* <p><b>null-safe 语义</b>:{@link MeterRegistry} 为 null 时(即未启用指标),全部 7 个内部
* 字段为 null,所有 record 方法走 no-op 路径。
*
* <p><b>线程安全</b>:本类仅在 cache 构造期由单线程初始化;运行期 record 方法调
Expand Down Expand Up @@ -69,7 +67,7 @@ final class RedisProCacheMetricsRegistry {

private final String cacheName;

// 写侧 6 字段:3 Timer + 4 Counter
// 写侧 7 字段:3 Timer + 4 Counter
// 注:clear 路径无 Counter(batch 操作语义不适合计数),仅 Timer
@Nullable
private final Timer getTimer;
Expand All @@ -87,22 +85,21 @@ final class RedisProCacheMetricsRegistry {
private final Counter evictCounter;

/**
* 构造期一次性注册 6 个 metric — 在 cache 构造期调用一次,运行期 record 路径直接复用。
* 构造期一次性注册 7 个 metric — 在 cache 构造期调用一次,运行期 record 路径直接复用。
*
* <p>内部委派 {@link RedisProCacheTimers} 原语(registerTimer / registerCounter)保证 null-safe 语义。
*
* @param meterRegistry Micrometer 注册表(可为 null → 全部 6 字段为 null)
* <p>内部注册 helper 保证 {@code meterRegistry == null} 时所有字段保持 null。
* @param meterRegistry Micrometer 注册表(可为 null → 全部 7 字段为 null)
* @param cacheName cache 标识,作为 {@code tags("cache", cacheName)} 写入每个 metric
*/
public RedisProCacheMetricsRegistry(@Nullable MeterRegistry meterRegistry, String cacheName) {
this.cacheName = cacheName;
this.getTimer = RedisProCacheTimers.registerTimer(meterRegistry, TIMER_GET, DESC_GET_TIMER, cacheName);
this.putTimer = RedisProCacheTimers.registerTimer(meterRegistry, TIMER_PUT, DESC_PUT_TIMER, cacheName);
this.evictTimer = RedisProCacheTimers.registerTimer(meterRegistry, TIMER_EVICT, DESC_EVICT_TIMER, cacheName);
this.hitCounter = RedisProCacheTimers.registerCounter(meterRegistry, COUNTER_HIT, DESC_HIT, cacheName);
this.missCounter = RedisProCacheTimers.registerCounter(meterRegistry, COUNTER_MISS, DESC_MISS, cacheName);
this.putCounter = RedisProCacheTimers.registerCounter(meterRegistry, COUNTER_PUT, DESC_PUT, cacheName);
this.evictCounter = RedisProCacheTimers.registerCounter(meterRegistry, COUNTER_EVICT, DESC_EVICT, cacheName);
this.getTimer = registerTimer(meterRegistry, TIMER_GET, DESC_GET_TIMER, cacheName);
this.putTimer = registerTimer(meterRegistry, TIMER_PUT, DESC_PUT_TIMER, cacheName);
this.evictTimer = registerTimer(meterRegistry, TIMER_EVICT, DESC_EVICT_TIMER, cacheName);
this.hitCounter = registerCounter(meterRegistry, COUNTER_HIT, DESC_HIT, cacheName);
this.missCounter = registerCounter(meterRegistry, COUNTER_MISS, DESC_MISS, cacheName);
this.putCounter = registerCounter(meterRegistry, COUNTER_PUT, DESC_PUT, cacheName);
this.evictCounter = registerCounter(meterRegistry, COUNTER_EVICT, DESC_EVICT, cacheName);
}

// ==================== 业务方法(get / put / evict / clear) ====================
Expand All @@ -120,21 +117,21 @@ public RedisProCacheMetricsRegistry(@Nullable MeterRegistry meterRegistry, Strin
* @return body.get() 的结果
*/
public <T> T recordGet(Supplier<T> body) {
return RedisProCacheTimers.timedGet(getTimer, body);
return timedGet(getTimer, body);
}

/**
* 记录 hit 计数(get 返回非 null 时调用)— null-safe。
*/
public void recordHit() {
RedisProCacheTimers.safeIncrement(hitCounter);
safeIncrement(hitCounter);
}

/**
* 记录 miss 计数(get 返回 null 时调用)— null-safe。
*/
public void recordMiss() {
RedisProCacheTimers.safeIncrement(missCounter);
safeIncrement(missCounter);
}

/**
Expand All @@ -145,15 +142,15 @@ public void recordMiss() {
public void recordPut(Runnable body) {
if (putTimer == null) {
body.run();
increment(putCounter);
safeIncrement(putCounter);
return;
}
long start = System.nanoTime();
try {
body.run();
} finally {
putTimer.record(System.nanoTime() - start, TimeUnit.NANOSECONDS);
increment(putCounter);
safeIncrement(putCounter);
}
}

Expand All @@ -165,15 +162,15 @@ public void recordPut(Runnable body) {
public void recordEvict(Runnable body) {
if (evictTimer == null) {
body.run();
increment(evictCounter);
safeIncrement(evictCounter);
return;
}
long start = System.nanoTime();
try {
body.run();
} finally {
evictTimer.record(System.nanoTime() - start, TimeUnit.NANOSECONDS);
increment(evictCounter);
safeIncrement(evictCounter);
}
}

Expand All @@ -183,7 +180,7 @@ public void recordEvict(Runnable body) {
* @param body 实际的 clear 操作(不可为 null)
*/
public void recordClear(Runnable body) {
RedisProCacheTimers.timed(evictTimer, body);
timed(evictTimer, body);
}

/**
Expand Down Expand Up @@ -212,8 +209,57 @@ String cacheName() {

// ==================== 私有 helper ====================

private static void increment(@Nullable Counter counter) {
RedisProCacheTimers.safeIncrement(counter);
private static Timer registerTimer(@Nullable MeterRegistry registry, String name,
String description, String cacheName) {
if (registry == null) {
return null;
}
return Timer.builder(name)
.tag("cache", cacheName)
.description(description)
.register(registry);
}

private static Counter registerCounter(@Nullable MeterRegistry registry, String name,
String description, String cacheName) {
if (registry == null) {
return null;
}
return Counter.builder(name)
.tag("cache", cacheName)
.description(description)
.register(registry);
}

private static void safeIncrement(@Nullable Counter counter) {
if (counter != null) {
counter.increment();
}
}

private static void timed(@Nullable Timer timer, Runnable body) {
if (timer == null) {
body.run();
return;
}
long start = System.nanoTime();
try {
body.run();
} finally {
timer.record(System.nanoTime() - start, TimeUnit.NANOSECONDS);
}
}

private static <T> T timedGet(@Nullable Timer timer, Supplier<T> body) {
if (timer == null) {
return body.get();
}
long start = System.nanoTime();
try {
return body.get();
} finally {
timer.record(System.nanoTime() - start, TimeUnit.NANOSECONDS);
}
}

private static long countOf(@Nullable Counter counter) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
* <ul>
* <li>调用方关心「这个 cache 的指标快照」语义而非多个独立 getter — deep 方法</li>
* <li>派生字段(hitRate)由 record 工厂方法计算,调用方不写算术</li>
* <li>Counter/Timer 字段由 {@code RedisProCacheTimers} 维护 null-safe 语义,
* <li>Counter/Timer 字段由
* {@link io.github.davidhlp.spring.cache.redis.cache.RedisProCacheMetricsRegistry} 维护 null-safe 语义,
* 本 record 工厂方法对 {@code null} Counter 返回 {@code 0L}</li>
* <li>新增指标(hit-ratio / 复合 timer 等)只在本 record 加字段 + 工厂方法加一行,
* 不污染 RedisProCache public surface</li>
Expand Down
Loading
Loading