如何在Spring Boot中监控缓存的命中率?

发布于:2025-02-27 ⋅ 阅读:(15) ⋅ 点赞:(0)

在 Spring Boot 中监控缓存的命中率对于评估缓存的有效性和性能优化至关重要。下面为你详细介绍不同缓存实现下监控缓存命中率的方法。

1. 使用 Spring Cache 和 SimpleCacheManager

1.1 配置 SimpleCacheManager

SimpleCacheManager 是 Spring 提供的一个简单的缓存管理器,适合开发和测试环境。首先,在配置类中配置 SimpleCacheManager

收起

java

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        cacheManager.setCaches(Arrays.asList(
                new ConcurrentMapCache("myCache")
        ));
        return cacheManager;
    }
}
1.2 自定义缓存统计

由于 SimpleCacheManager 本身不直接提供命中率统计功能,我们可以自定义一个包装类来实现统计。

收起

java

import org.springframework.cache.Cache;
import org.springframework.cache.concurrent.ConcurrentMapCache;

import java.util.concurrent.atomic.AtomicInteger;

public class CustomConcurrentMapCache extends ConcurrentMapCache {

    private final AtomicInteger hits = new AtomicInteger(0);
    private final AtomicInteger misses = new AtomicInteger(0);

    public CustomConcurrentMapCache(String name) {
        super(name);
    }

    @Override
    public ValueWrapper get(Object key) {
        ValueWrapper result = super.get(key);
        if (result != null) {
            hits.incrementAndGet();
        } else {
            misses.incrementAndGet();
        }
        return result;
    }

    public int getHits() {
        return hits.get();
    }

    public int getMisses() {
        return misses.get();
    }

    public double getHitRate() {
        int total = hits.get() + misses.get();
        return total == 0 ? 0 : (double) hits.get() / total;
    }
}

然后在配置类中使用自定义的缓存类。

收起

java

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        cacheManager.setCaches(Arrays.asList(
                new CustomConcurrentMapCache("myCache")
        ));
        return cacheManager;
    }
}
1.3 监控缓存命中率

在需要监控的地方获取自定义缓存并计算命中率。

收起

java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;

@Service
public class CacheMonitoringService {

    @Autowired
    private CacheManager cacheManager;

    public double getCacheHitRate(String cacheName) {
        Cache cache = cacheManager.getCache(cacheName);
        if (cache instanceof CustomConcurrentMapCache) {
            CustomConcurrentMapCache customCache = (CustomConcurrentMapCache) cache;
            return customCache.getHitRate();
        }
        return 0;
    }
}

2. 使用 Caffeine 缓存

2.1 添加依赖

在 pom.xml 中添加 Caffeine 缓存依赖。

收起

xml

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.1.6</version>
</dependency>
2.2 配置 Caffeine 缓存管理器

收起

java

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager("myCache");
        cacheManager.setCaffeine(caffeineCacheBuilder());
        return cacheManager;
    }

    private Caffeine<Object, Object> caffeineCacheBuilder() {
        return Caffeine.newBuilder()
              .initialCapacity(100)
              .maximumSize(500)
              .expireAfterWrite(10, TimeUnit.MINUTES)
              .recordStats();
    }
}

注意,recordStats() 方法用于开启缓存统计功能。

2.3 监控缓存命中率

收起

java

import com.github.benmanes.caffeine.cache.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.stereotype.Service;

@Service
public class CacheMonitoringService {

    @Autowired
    private CacheManager cacheManager;

    public double getCacheHitRate(String cacheName) {
        org.springframework.cache.Cache springCache = cacheManager.getCache(cacheName);
        if (springCache instanceof CaffeineCache) {
            CaffeineCache caffeineCache = (CaffeineCache) springCache;
            Cache<Object, Object> nativeCache = caffeineCache.getNativeCache();
            return nativeCache.stats().hitRate();
        }
        return 0;
    }
}

3. 使用 Redis 缓存

3.1 添加依赖

在 pom.xml 中添加 Redis 缓存依赖。

收起

xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
3.2 配置 Redis 缓存管理器

收起

java

import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@Configuration
public class CacheConfig {

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
              .entryTtl(Duration.ofMinutes(10))
              .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
              .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));

        return RedisCacheManager.builder(redisConnectionFactory)
              .cacheDefaults(cacheConfig)
              .build();
    }
}
3.3 监控缓存命中率

Redis 本身提供了一些命令来监控缓存命中率,例如 INFO stats 命令可以获取 keyspace_hits 和 keyspace_misses 信息。在 Spring Boot 中,可以使用 RedisTemplate 来执行这些命令。

收起

java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Map;

@Service
public class CacheMonitoringService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public double getRedisCacheHitRate() {
        RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
        String info = new String(connection.info("stats"));
        String[] lines = info.split("\r\n");
        long hits = 0;
        long misses = 0;
        for (String line : lines) {
            if (line.startsWith("keyspace_hits:")) {
                hits = Long.parseLong(line.split(":")[1]);
            } else if (line.startsWith("keyspace_misses:")) {
                misses = Long.parseLong(line.split(":")[1]);
            }
        }
        long total = hits + misses;
        return total == 0 ? 0 : (double) hits / total;
    }
}

通过以上方法,你可以在 Spring Boot 中对不同的缓存实现进行命中率监控,从而更好地优化缓存配置和系统性能。