一、热点数据预加载

// 使用Redis HyperLogLog统计访问频率  
public void recordAccess(Long productId) {  
    String key = "access:product:" + productId;  
    redis.pfadd(key, UUID.randomUUID().toString());  
    redis.expire(key, 60); // 统计最近60秒  
}  

// 定时任务检测热点  
@Scheduled(fixedRate = 10000)  
public void detectHotKeys() {  
    Set<String> keys = redis.keys("access:product:*");  
    keys.forEach(key -> {  
        long count = redis.pfcount(key);  
        if (count > 1000) { // 阈值  
            Long productId = extractId(key);  
            preloadProduct(productId);  
        }  
    });  
}

二、空值缓存

public Product getProduct(Long id) {  
    String key = "product:" + id;  
    Product product = redis.get(key);  
    if (product != null) {  
        if (product.isEmpty()) { // 空对象标识  
            return null;  
        }  
        return product;  
    }  

    product = productDao.findById(id);  
    if (product == null) {  
        redis.setex(key, 300, "empty"); // 缓存空值5分钟  
        return null;  
    }  

    redis.setex(key, 3600, product);  
    return product;  
}

三、需要增加熔断降级

@HystrixCommand(fallbackMethod = "getProductFallback",  
               commandProperties = {  
                   @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),  
                   @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000")  
               })  
public Product getProduct(Long id) {  
    return productDao.findById(id);  
}  

public Product getProductFallback(Long id) {  
    return new Product().setDefault(); // 返回兜底数据  
}

四、延迟双删策略

@Transactional  
public void updateProduct(Product product) {  
    // 1. 先删缓存  
    redis.delete("product:" + product.getId());  

    // 2. 更新数据库  
    productDao.update(product);  

    // 3. 延时再删  
    executor.schedule(() -> {  
        redis.delete("product:" + product.getId());  
    }, 500, TimeUnit.MILLISECONDS);  
}

粗眉毛的硬盘
1 声望0 粉丝