Bài hôm nay sẽ giới thiệu đến với các bạn khái niệm về Redis Cache là gì và cách ứng dụng với Spring Boot để tăng performance.

1. Giới thiệu

1.1 Redis Cache là gì ?

Redis là một Hệ Thống lưu trữ theo dạng Key-Value, dữ liệu của Redis được lưu trữ trực tiếp trên RAM của Server nên điều này sẽ làm cho việc đọc dữ liệu trở nên nhanh hơn nhiều lần so với đọc từ database hay đọc file từ ổ cứng.

Các bạn có thể tìm hiểu thêm thông tin của Redis tại trang chủ redis.io

1.2 Các đặc điểm của Redis Cache:

  •  Giới hạn bộ nhớ tối đa: Mặc định Redis sẽ là 32GB đối với Server 32-bit và không có giới hạn đối với Server 64-bit. Các bạn lưu ý rằng giới hạn ở đây là bộ nhớ tối đa mà chúng ta có thể cấp cho Redis cache dựa theo tài nguyên của Server, ví dụ Server của bạn có 16GB RAM thì bạn chỉ có thể cấp tối đa cho Redis khoảng tầm chừng 4 - 8GB.
  • Thuật toán xoá cache: Khi dữ liệu trong cache đạt tới ngưỡng lưu trữ tối đa thì dữ liệu cũ nhất sẽ được xoá đi để ghi dữ liệu mới vào Cache
  • Độ ổn định (durability): Bạn sẽ phải cần lưu backup dữ liệu trong cache xuống một ví trí nào đó, trong database hoặc đơn giản là xuống file. Vì nếu Redis Cache gặp sự cố và bị shutdown thì các bạn đã biết dữ liệu trên RAM sẽ bị xoá sạch nếu ứng dụng bị tắt, hoặc đơn giản nếu chúng ta restart Redis Cache cũng sẽ bị xoá sạch dữ liệu và chúng ta lại phải mất thời gian load cache lại từ đầu. Do đó nếu trước đó đã có lưu trữ lại dữ liệu thì sau khi start lại, Redis Cache sẽ đọc và load dữ liệu vào lại bên trong Cache như trước đó.

1.3 Vì sao nên sử dụng Cache trong Spring ?

Spring Boot hay bất kỳ Web Framework nào cũng sẽ có độ trễ nhất định để xử lý dữ liệu trả về cho người dùng, dữ liệu càng lớn xử lý càng phức tạp thì thời gian trả về càng lâu. Và nếu ngừoi dùng yêu cầu liên tục thì sẽ có khả năng dẫn đến quá tải server đồng thời làm kém đi trải nghiệm người dùng.

Do đó, với những dữ liệu nào thường được truy cập thường xuyên nếu được cache lại và trả về cho người dùng ngay mà không cần phải tốn thời gian xử lý, khoảng thời gian người dùng phải chờ lúc này chỉ là vấn đề phụ thuộc vào tốc độ đường truyền và độ lớn của dữ liệu.

Ví dụ: ngày hôm nay là chốt sổ khoá tài chính trong năm vừa qua, các số liệu tổng hợp của tháng, quý sẽ được các phòng ban liên tục truy cập để hoàn thành sổ sách, do đó cần phải cache lại những dữ liệu này để có thể lập tức trả về ngay mà không cần phải xử lý lại từ đầu từ những hoá đơn mua bán, thanh toán, ....

1.4 Hướng dẫn Cài đặt Redis Cache

- Trên Windows: Các bạn download gói cài đặt dành cho Windows từ trang chủ của redis.io. Và bấm next liên tục trên trình hướng dẫn. Sau khi cài đặt xong, Redis sẽ được Windows register như là 1 service. Mở folder cài đặt của Redis và chạy file redis-server.exe, chúng ta sẽ được như sau:

 


- Trên Linux - Ubuntu:

sudo apt install redis-server
sudo systemctl status redis-server

Sau khi cài đặt thành công, chúng ta sẽ có output tương tự sau:

redis-server.service - Advanced key-value store
   Loaded: loaded (/lib/systemd/system/redis-server.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2018-10-28 0545 PDT; 2h ago
     Docs: https://redis.io/documentation,
           man:redis-server(1)
  Process: 2197 ExecStop=/bin/kill -s TERM $MAINPID (code=exited, status=0/SUCCESS)
  Process: 2201 ExecStart=/usr/bin/redis-server /etc/redis/redis.conf (code=exited, status=0/SUCCESS)
 Main PID: 2226 (redis-server)
    Tasks: 4 (limit: 2319)
   CGroup: /system.slice/redis-server.service
           `-2226 /usr/bin/redis-server 0.0.0.0:6379

​


 

2. Sử dụng Redis trong Spring

2.1 Project Spring Boot

Trước khi vào hướng dẫn tích hợp Redis Cache đầu tiên chúng ta phải cần có 1 project Spring Boot trước. Các bạn có thể download tại bài hướng dẫn trước tại đây

2.2 Thư viện Maven

Các bạn thêm 2 thư viện Maven như bên dưới vào dependencies:

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>2.0.3.RELEASE</version>
 </dependency>
 
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
    <type>jar</type>
</dependency>

2.3 Cấu hình Redis bằng application.properties

spring.cache.type=redis
spring.redis.host=192.168.xx.xx
spring.redis.port=6379

Spring Boot hỗ trợ các property khai báo cấu hình cho Redis Cache tương tự như khai báo Datasource cho Database vậy.

2.4 Khai báo Cache Manager

Với Spring Boot việc khai báo Cache bằng Annotation rất đơn giản, các bạn tạo 1 class WebConfig như sau:

import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

@Configuration
public class WebConfig {

    @Bean
    public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        Cache singlePostSeoUrlCache = new ConcurrentMapCache("singlePost");
        Cache menuListCache = new ConcurrentMapCache("menuList");

        cacheManager.setCaches(Arrays.asList(singlePostSeoUrlCache, menuListCache));
        return cacheManager;
    }
}

Các bạn chú ý rằng: chúng ta sẽ cần phải khai báo hết những phần cache sẽ được sử dụng tại class này. Như trong ví dụ, mình sẽ cache lại danh sách Menu và dữ liệu cho 1 bài viết được yêu cầu theo Url.

2.5 Cấu hình @Cacheable

@Cacheable

Đánh dấu API (hoặc method) mà chúng ta cần cache.

Ở đây chúng ta sẽ cache lại dữ liệu của 1 bài viết dựa theo Id của nó. Nghĩa là khi người dùng yêu cầu mỗi bài viết thì trong cache sẽ được check trước theo key là Id của bài viết, nếu có trong cache sẽ lập tức trả về cho người dùng ngay, nếu chưa có thì sẽ query database để lấy và tất nhiên là sẽ cache lại.

    /**
     * find post by id
     *
     * @param id
     * @return
     */
    @GetMapping(value = "/{id}")
    @Cacheable(value = "singlePost", key = "#id")
    public Post findById(@PathVariable(value = "id") Long id) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return postRepository.getOne(id);
    }


@CachePut

Update dữ liệu trong cache khi có sự thay đổi.

​@CachePut(value = "postSingle", 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

Xoá dữ liệu trong cache khi chúng ta xoá dữ liệu ra khỏi hệ thống:

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


2.6 Enable caching trên class Main

Để có thể sử dụng được Cache cho Spring Boot chúng ta cần phải enable Cache bằng annotation @EnableCaching như sau:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

Chúc các bạn thành công.

AutoCode.VN

minhnhatict@gmail.com Tools