Java案例怎么清理过期缓存?

wen java案例 9

本文目录导读:

Java案例怎么清理过期缓存?

  1. 使用Guava Cache(推荐)
  2. 使用Caffeine Cache(性能更好)
  3. 自定义延时清理方案
  4. 使用Redis(分布式场景)
  5. 使用Ehcache
  6. 最佳实践建议

在Java中清理过期缓存有多种实现方式,这里提供几个常用的案例方案:

使用Guava Cache(推荐)

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.TimeUnit;
public class GuavaCacheExample {
    // 创建缓存,设置过期策略
    private static Cache<String, Object> cache = CacheBuilder.newBuilder()
        // 写入后10分钟过期
        .expireAfterWrite(10, TimeUnit.MINUTES)
        // 访问后5分钟过期(如果没被访问则过期)
        .expireAfterAccess(5, TimeUnit.MINUTES)
        // 设置最大缓存数量
        .maximumSize(1000)
        .build();
    public static void main(String[] args) {
        // 存入缓存
        cache.put("key1", "value1");
        // 获取缓存(如果过期返回null)
        Object value = cache.getIfPresent("key1");
        // 移除缓存
        cache.invalidate("key1");
        // 清理所有过期缓存(Guava自动清理,也可手动调用)
        cache.cleanUp();
    }
}

使用Caffeine Cache(性能更好)

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.concurrent.TimeUnit;
public class CaffeineCacheExample {
    private static Cache<String, Object> cache = Caffeine.newBuilder()
        // 写入后5分钟过期
        .expireAfterWrite(5, TimeUnit.MINUTES)
        // 访问后2分钟过期
        .expireAfterAccess(2, TimeUnit.MINUTES)
        // 最大缓存数
        .maximumSize(5000)
        // 缓存淘汰监听器
        .removalListener((key, value, cause) -> {
            System.out.println("缓存被移除: " + key + ", 原因: " + cause);
        })
        .build();
    public static void main(String[] args) {
        cache.put("user_001", userData);
        // 获取缓存,如果过期返回null
        Object data = cache.getIfPresent("user_001");
        // 自动清理过期缓存(Caffeine会自动执行)
        cache.cleanUp();
    }
}

自定义延时清理方案

import java.util.concurrent.*;
public class CustomCacheCleaner {
    private static ConcurrentHashMap<String, CacheEntry> cache = new ConcurrentHashMap<>();
    private static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    static class CacheEntry {
        Object value;
        long expireTime;
        CacheEntry(Object value, long expireTime) {
            this.value = value;
            this.expireTime = expireTime;
        }
        boolean isExpired() {
            return System.currentTimeMillis() > expireTime;
        }
    }
    // 启动定时清理任务
    static {
        scheduler.scheduleAtFixedRate(() -> {
            cleanExpiredCache();
        }, 0, 1, TimeUnit.MINUTES); // 每分钟执行一次
    }
    // 存入缓存(带过期时间)
    public static void put(String key, Object value, long ttl, TimeUnit unit) {
        long expireTime = System.currentTimeMillis() + unit.toMillis(ttl);
        cache.put(key, new CacheEntry(value, expireTime));
    }
    // 获取缓存(自动检查过期)
    public static Object get(String key) {
        CacheEntry entry = cache.get(key);
        if (entry == null || entry.isExpired()) {
            cache.remove(key);
            return null;
        }
        return entry.value;
    }
    // 清理过期缓存
    public static void cleanExpiredCache() {
        long now = System.currentTimeMillis();
        cache.entrySet().removeIf(entry -> entry.getValue().isExpired());
    }
}

使用Redis(分布式场景)

import org.springframework.data.redis.core.RedisTemplate;
import java.util.concurrent.TimeUnit;
public class RedisCacheExample {
    private RedisTemplate<String, Object> redisTemplate;
    // 存入缓存,设置过期时间
    public void setWithExpire(String key, Object value, long timeout, TimeUnit unit) {
        redisTemplate.opsForValue().set(key, value, timeout, unit);
    }
    // 获取缓存(Redis自动处理过期)
    public Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }
    // 手动清理过期键
    public void cleanExpiredKeys() {
        // Redis的key过期是由Redis自身管理的
        // 这里可以批量删除某些模式的key
        Set<String> keys = redisTemplate.keys("pattern:*");
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
        }
    }
}

使用Ehcache

import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ExpiryPolicyBuilder;
import java.time.Duration;
public class EhcacheExample {
    public static void main(String[] args) {
        CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build();
        cacheManager.init();
        Cache<String, Object> cache = cacheManager.createCache("myCache",
            CacheConfigurationBuilder.newCacheConfigurationBuilder(
                String.class, Object.class,
                // 设置过期时间
                ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(10))
            ));
        cache.put("key", "value");
        Object value = cache.get("key");
        // Ehcache自动清理过期缓存
        cacheManager.close();
    }
}

最佳实践建议

  1. 选择合适工具:单机应用推荐Guava或Caffeine,分布式应用推荐Redis
  2. 设置合理过期时间:根据业务需求设置TTL
  3. 结合懒清理:访问时检查过期比定时清理更高效
  4. 监控缓存使用:定期检查缓存命中率,调整策略
// 懒清理示例(访问时检查)
public Object getFromCache(String key) {
    CacheEntry entry = cache.get(key);
    if (entry != null && entry.isExpired()) {
        cache.remove(key);  // 清理过期缓存
        return null;
    }
    return entry != null ? entry.value : null;
}

选择哪种方案取决于你的具体场景:单机应用推荐Caffeine/Guava,分布式系统推荐Redis。

抱歉,评论功能暂时关闭!