動態

詳情 返回 返回

分享四個關於網站緩存的技巧 - 動態 詳情

一、熱點數據預加載

// 使用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);  
}

Add a new 評論

Some HTML is okay.