Careeroza
Redis Distributed Cache
When You Need Redis
With 4 ShopEase instances behind a load balancer, each Caffeine cache is separate: an update on server 1 evicts only server 1's copy. Redis is a shared, external cache, so all instances see the same entries and evictions.
+-----------+
user ---> | Load | ---> app-1 --+
| Balancer | ---> app-2 --+---> Redis (shared cache) ---> MySQL (on miss)
+-----------+ ---> app-3 --+Setup
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>Example
application.yml
spring:
cache:
type: redis
redis:
time-to-live: 10m
key-prefix: "shopease::"
cache-null-values: false
data:
redis:
host: ${REDIS_HOST:localhost}
port: 6379
password: ${REDIS_PASSWORD:}@Bean
RedisCacheManagerBuilderCustomizer redisCaches() {
var json = RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()); // store JSON, not Java serialization
return builder -> builder
.withCacheConfiguration("products",
RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)).serializeValuesWith(json))
.withCacheConfiguration("stock",
RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(15)).serializeValuesWith(json));
}Looking Inside Redis
Example
The same @Cacheable code now stores entries in Redis:
docker run -d --name redis -p 6379:6379 redis:7
curl -s localhost:8080/api/products/3 > /dev/null
redis-cli KEYS "shopease::*"
redis-cli TTL "shopease::products::3"Example output
1) "shopease::products::3" (integer) 597
| Caffeine | Redis | |
|---|---|---|
| Location | inside the JVM | separate server |
| Speed | nanoseconds | about 1 ms (network) |
| Shared across instances | no | yes |
| Survives restart | no | yes (if persistence is on) |