Careeroza
Real World Example
Big Billion Days Product Pages
During sales like Flipkart's Big Billion Days, millions of users open the same few hundred product pages. Shops use two cache levels: a tiny Caffeine cache (a few seconds) in each instance in front of Redis (minutes), with eviction when a seller changes a price.
@Service
@RequiredArgsConstructor
public class ProductCatalog {
private final ProductRepository repo;
private final CacheManager redisCacheManager;
private final Cache<Long, ProductDto> local = Caffeine.newBuilder()
.maximumSize(5_000).expireAfterWrite(Duration.ofSeconds(5)).build();
public ProductDto get(Long id) {
return local.get(id, key -> {
var redis = redisCacheManager.getCache("products");
ProductDto cached = redis.get(key, ProductDto.class);
if (cached != null) return cached;
ProductDto fresh = repo.findById(key).map(ProductDto::from).orElseThrow();
redis.put(key, fresh);
return fresh;
});
}
@Transactional
public ProductDto changePrice(Long id, BigDecimal price) {
Product p = repo.findById(id).orElseThrow();
p.setPrice(price);
redisCacheManager.getCache("products").evict(id);
local.invalidate(id);
return ProductDto.from(p);
}
}Example
Effect measured with a load test:
wrk -t4 -c200 -d30s http://localhost:8080/api/products/3Example output
no cache Redis only Caffeine + Redis p50 latency 48 ms 6 ms 1.2 ms req/sec 3,900 21,000 58,000 DB queries 117,000 14 14
Note: Other instances keep their local copy for up to 5 seconds after a price change. That is acceptable for a product page, but the checkout always reads price and stock from the database.