Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B38FGKKam5SCGgwgduVAh3
64 lines
3.0 KiB
Markdown
64 lines
3.0 KiB
Markdown
[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)
|