Beyond @Cacheable: 4 Redis Design Patterns That Separate Good Coders from System Architects
The article explains why merely adding @Cacheable is insufficient and introduces four essential Redis design patterns—penetration protection, avalanche mitigation, serialization control, and consistency handling—plus client‑level considerations, each illustrated with concrete code and diagrams.
Technical Depth
Adding three @Cacheable annotations reduced database load by 40%, but when Redis memory reached 100% sessions were lost and stale data was returned, highlighting the need for systematic Redis design.
Cache Penetration Protection
Problem: Queries for non‑existent data return null; Spring does not cache null, causing repeated database hits under high concurrency.
Typical wrong code:
@Cacheable("products")
public Product findById(Long id) {
return productRepository.findById(id).orElse(null);
}Correct approach – cache empty objects:
@Cacheable(value = "products", unless = "#result == null")
public Product findById(Long id) {
return productRepository.findById(id).orElseGet(() -> Product.empty());
}Manual control example:
public Product findById(Long id) {
String key = "product:" + id;
Product cache = redisTemplate.opsForValue().get(key);
if (cache != null) {
return cache;
}
Product db = productRepository.findById(id).orElse(null);
redisTemplate.opsForValue().set(key,
db == null ? Product.empty() : db,
5, TimeUnit.MINUTES);
return db;
}Cache Avalanche Mitigation
When many keys expire simultaneously the database can be flooded.
Solution: randomize TTL.
public void cacheWithRandomTTL(String key, Object value) {
int baseTtl = 3600; // 1 hour
int random = ThreadLocalRandom.current().nextInt(300); // up to 5 minutes
redisTemplate.opsForValue().set(key, value, baseTtl + random, TimeUnit.SECONDS);
}Serialization Strategy
Default JDK serialization produces unreadable keys and consumes extra memory.
Configure RedisTemplate to use JSON serialization:
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer<Object> serializer =
new Jackson2JsonRedisSerializer<>(Object.class);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}Key: human‑readable for easier troubleshooting.
Value: JSON for cross‑language compatibility and space savings.
Avoid default JDK serialization.
Cache Consistency Strategy
Database updates do not automatically refresh cached entries, leading to stale reads.
Wrong pattern – evicting all entries:
@CacheEvict(value = "products", allEntries = true)
public Product updateProduct(Product product) {
return productRepository.save(product);
}Recommended double‑delete pattern:
public void updateProduct(Product product) {
String key = "product:" + product.getId();
// First delete
redisTemplate.delete(key);
// Update DB
productRepository.save(product);
// Delayed second delete to avoid race conditions
Executors.newSingleThreadScheduledExecutor().schedule(() -> {
redisTemplate.delete(key);
}, 500, TimeUnit.MILLISECONDS);
}Lettuce Client and Connection Management
Spring Boot defaults to Lettuce, a Netty‑based asynchronous client. Its thread model and connection pool affect performance.
Basic configuration:
spring:
redis:
host: 127.0.0.1
port: 6379
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0Optimization tips:
Configure the connection pool according to workload.
Avoid blocking calls that block Netty event loops.
Monitor active connections under high concurrency.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
LuTiao Programming
LuTiao Programming is a friendly community offering free programming lessons. We inspire learners to explore new ideas and technologies and quickly acquire job-ready skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
