waltcow / blog

A personal blog
21 stars 2 forks source link

Spring Boot cache with Redis #50

Open waltcow opened 4 years ago

waltcow commented 4 years ago

Cache abstraction

Spring Framework provides an abstraction layer with set of annotations for caching support and can work together with various cache implementation like Redis, EhCache, Hazelcast, Infinispan and many more.

@Cacheable

Fulfill cache after method execution, next invocation with the same arguments will be omitted and result will be loaded from cache. Annotation provide useful feature called conditional caching. In some case no all data should be cached e.g. you want store in memory only most popular posts.

@Cacheable(value = "post-single", key = "#id", unless = "#result.shares < 500")
@GetMapping("/{id}")
public Post getPostByID(@PathVariable String id) throws PostNotFoundException {
    log.info("get post with id {}", id);
    return postService.getPostByID(id);
}
@Cacheable(value = "post-top")
@GetMapping("/top")
public List<Post> getTopPosts() {
    return postService.getTopPosts();
}

@CachePut

Annotation allows to update entry in cache and support same options like Cacheable annotation. Code below updates post and return it for cache provider to change entry with new value.

@CachePut(value = "post-single", key = "#post.id")
@PutMapping("/update")
public Post updatePostByID(@RequestBody Post post) throws PostNotFoundException {
    log.info("update post with id {}", post.getId());
    postService.updatePost(post);
    return post;
}

@CacheEvict

Remove entry from cache, can be both conditional and global to all entries in specific cache.

@CacheEvict(value = "post-single", key = "#id")
@DeleteMapping("/delete/{id}")
public void deletePostByID(@PathVariable String id) throws PostNotFoundException {
    log.info("delete post with id {}", id);
    postService.deletePost(id);
}

@CacheEvict(value = "post-top")
@GetMapping("/top/evict")
public void evictTopPosts() {
    log.info("Evict post-top");
}

@EnableCaching

Annotation ensure that post processor will check all beans trying to find demarcated methods and will create proxy to intercept all invocations.

@Caching

Aggregate multiple annotations of the same type when e.g. you need to use different conditions and caches.

@CacheConfig

Class level annotation allows to specify global values for annotations like cache name or key generator.

Hibernate Second-Level Cache

One of the advantages of database abstraction layers such as ORM (object-relational mapping) frameworks is their ability to transparently cache data retrieved from the underlying store. This helps eliminate database-access costs for frequently accessed data.

What Is a Second-Level Cache?

As most other fully-equipped ORM frameworks, Hibernate has the concept of first-level cache. It is a session scoped cache which ensures that each entity instance is loaded only once in the persistent context.

Once the session is closed, first-level cache is terminated as well. This is actually desirable, as it allows for concurrent sessions to work with entity instances in isolation from each other.

On the other hand, second-level cache is SessionFactory-scoped, meaning it is shared by all sessions created with the same session factory. When an entity instance is looked up by its id (either by application logic or by Hibernate internally, e.g. when it loads associations to that entity from other entities), and if second-level caching is enabled for that entity, the following happens:

Once the instance is stored in the persistence context (first-level cache), it is returned from there in all subsequent calls within the same session until the session is closed or the instance is manually evicted from the persistence context. Also, the loaded instance state is stored in L2 cache if it was not there already.

Spring Boot cache with Redis

Hibernate Second-Level Cache

spring-cache-tutorial