Files

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)