Add redis: Boot 4.1 + Spring Data Redis 4.1, the JDK-serialisation default vs Jackson 3 serializers, @RedisHash TTL and keyspace events, @RedisListener, and Redis as the Spring cache
Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B38FGKKam5SCGgwgduVAh3
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
[Home](../README.md) | Prev: [TTL](08-ttl.md) | Next: [Production checklist](10-production-checklist.md)
|
||||
|
||||
# 9. Redis as the Spring cache
|
||||
|
||||
The annotations (`@Cacheable`, `@CacheEvict`, keys, the self-invocation trap) are covered in
|
||||
[The Spring Cache Abstraction](https://ankurm.com/spring-cache-abstraction-cacheable-cacheevict-self-invocation-trap/) and its
|
||||
[companion project](../../caching). This chapter is only about what changes when the cache is Redis.
|
||||
|
||||
With `spring-boot-starter-cache` and the Redis starter on the classpath and `@EnableCaching`, Boot
|
||||
picks `org.springframework.data.redis.cache.RedisCacheManager`
|
||||
([14-cache-default.txt](output/14-cache-default.txt)). [UserService](../src/main/java/com/ankurm/redis/cache/UserService.java)
|
||||
has two cached methods that differ only in whether the result is `Serializable`.
|
||||
|
||||
## What the defaults store
|
||||
|
||||
Keys are readable: `<cacheName>::<key>`, here `legacy::1`. The value is JDK-serialised, exactly as in
|
||||
[chapter 2](02-default-serialization.md):
|
||||
|
||||
```
|
||||
$ redis-cli -p 6390 --no-raw GET legacy::1
|
||||
"\xac\xed\x00\x05sr\x00'com.ankurm.redis.model.SerializableUser..."
|
||||
```
|
||||
|
||||
`spring.cache.redis.time-to-live=10m` works: `TTL legacy::1` is `600`.
|
||||
|
||||
A result that is **not** `Serializable` is not cached, and the *method call fails*:
|
||||
|
||||
```
|
||||
java.lang.IllegalStateException
|
||||
message: Cannot serialize value of type com.ankurm.redis.model.User without a serializer
|
||||
method body ran 2 time(s) in total
|
||||
```
|
||||
|
||||
The body ran (twice in total: once for the good call, once for the failing one), the write to Redis threw, and
|
||||
the caller sees the exception. A `@Cacheable` on a method returning a non-Serializable type breaks that method.
|
||||
|
||||
## Switching to JSON
|
||||
|
||||
Declare a `RedisCacheConfiguration` bean. [JsonCacheConfig](../src/main/java/com/ankurm/redis/config/JsonCacheConfig.java)
|
||||
(active under the `json-cache` profile) does it with the same allow-listed Jackson 3 serializer as
|
||||
[chapter 4](04-json-serializers.md) ([15-cache-json.txt](output/15-cache-json.txt)):
|
||||
|
||||
```
|
||||
$ redis-cli -p 6390 GET users::1
|
||||
{"@class":"com.ankurm.redis.model.User","id":1,"name":"Ankur"}
|
||||
```
|
||||
|
||||
The non-Serializable record now caches, and the method body ran once for two calls.
|
||||
|
||||
## The property that stops applying
|
||||
|
||||
The test sets `spring.cache.redis.time-to-live=10m` **and** declares a bean with
|
||||
`entryTtl(Duration.ofMinutes(5))`. The key's TTL is `300`. When you define your own
|
||||
`RedisCacheConfiguration`, Boot used that bean and the `spring.cache.redis.time-to-live` property had no effect
|
||||
on the TTL. Put the TTL in the bean.
|
||||
|
||||
## Going deeper
|
||||
|
||||
- [RedisCacheDefaultTest](../src/test/java/com/ankurm/redis/RedisCacheDefaultTest.java) and [RedisCacheJsonTest](../src/test/java/com/ankurm/redis/RedisCacheJsonTest.java)
|
||||
- [Spring Boot: Caching, Redis](https://docs.spring.io/spring-boot/reference/io/caching.html#io.caching.provider.redis)
|
||||
- [Spring Data Redis: Redis Cache](https://docs.spring.io/spring-data/redis/reference/redis/redis-cache.html)
|
||||
|
||||
[Home](../README.md) | Prev: [TTL](08-ttl.md) | Next: [Production checklist](10-production-checklist.md)
|
||||
Reference in New Issue
Block a user