Caching là một chủ đề khá quen thuộc trong lập trình, đặc biệt là lập trình web. Đây là một kỹ thuật đơn giản mà đặc biệt hiệu quả trong việc tăng tốc độ và giảm tải cho hệ thống. Trong bài viết này, chúng ta sẽ tìm hiểu Caching, một kĩ thuật được sử dụng trong hầu hết các hệ thống hiện nay và cách triển khai Caching trong Java với Redis hiệu quả.

1. Cache là gì?

1.1. Khái niệm về cache

Theo Wikipedia, cache là nơi chứa dữ liệu, nhằm giúp tăng tốc độ truy xuất dữ liệu ở những lần sau.

Trong một môi trường mạng thì Caching có thể được đặt ở gateway, proxy, web browser.

1.2. Lợi ích của cache

- Giúp tăng tốc truy xuất dữ liệu

- Giảm thiểu request tới bộ nhớ chính và cơ sở dữ liệu chính

- Giảm thiểu ảnh hưởng hiệu năng máy chủ do không mất thời gian cho việc tạo connection và truy vấn vào cơ sở dữ liệu

1.3. Hạn chế của cache

Có một câu nói rất nổi tiếng trong lịch sử phát triển của các kỹ thuật lập trình được thuật lại bởi lập trình viên Phil Karlton: “There are only two hard things in Computer Science: cache invalidation and naming things”. 

Nếu là một người chưa tìm hiểu cũng như chưa từng sử dụng cache thì bạn sẽ có câu hỏi là: Tại sao cache invalidation lại khó tới vậy? Thậm chí nó được ví như việc phải đặt tên biến cho hợp lý trong lập trình. 

Để trả lời cho các thắc mắc này, chúng ta sẽ cùng phân tích một số hạn chế dưới đây.

- Cache invalidation: nên nhớ cache là một bộ nhớ dữ liệu tạm thời và chỉ được sử dụng khi chúng ta cần lấy nó ra với mục đích làm giảm thời gian thao tác với dữ liệu từ các nguồn bộ nhớ. Chính vì thế, cache mà bị “out-of-date” thì nó sẽ trở nên vô dụng.

- Cache chỉ là một bộ nhớ lưu các dữ liệu tạm chứ không phải toàn bộ dữ liệu của hệ thống, vì vậy thường phải có thao tác đồng bộ dữ liệu từ bộ nhớ chính (cơ sở dữ liệu) vào cache. Cũng chính vì lý do này mà đôi khi Google chưa kịp đồng bộ cache thì ta vẫn có thể xem được các bài báo đã bị xoá trên website nhưng vẫn tồn tại trên Google cache.

Và để giải quyết vấn đề đồng bộ dữ liệu trên thì nhiều trường hợp ta cần thêm một tiến trình chạy ngầm để thực hiện đồng bộ, từ đó lại phát sinh việc giám sát tiến trình chạy ngầm này xem còn hoạt động ổn định hay không.

Với cache thì dữ liệu sẽ lưu trữ theo dạng key-value, nghĩa là khi lưu dữ liệu vào cache ta sẽ phải gắn dữ liệu đó với 1 key làm định danh, để khi cần lấy dữ liệu ra ta cũng phải sử dụng key định danh đó.

1.4. Lưu cái gì vào cache?

- Chính vì vấn đề “out-of-date” của cache nên thông thường người ta chỉ lưu các dữ liệu ít thay đổi ví dụ như danh sách địa bàn tỉnh thành, quốc gia.

- Lợi ích to lớn của cache là khả năng truy vấn dữ liệu nhanh nên người ta có thể lưu trữ các dữ liệu có tần suất sử dụng cao để giảm thiểu số lượng truy vấn vào cơ sở dữ liệu chính.

2. Redis

Redis được viết tắt từ Remote Dictionary Server, đây là hệ thống lưu trữ dữ liệu in-memory dưới dạng key-value với tốc độ nhanh, mã nguồn mở, được sử dụng để lưu trữ dữ liệu, cache, message broker và queue. 

Redis hỗ trợ nhiều cấu trúc dữ liệu cơ bản như string, hash, list, set, sorted set. Bên cạnh việc lưu trữ key-value trên RAM với hiệu năng cao, Redis còn hỗ trợ lưu trữ dữ liệu trên đĩa cứng cho phép phục hồi dữ liệu khi gặp sự cố. 

Redis hiện cung cấp thời gian phản hồi dưới một phần nghìn giây và cho phép hàng triệu yêu cầu mỗi giây dành cho các ứng dụng real-time trong gaming, ad-tech, dịch vụ tài chính, chăm sóc sức khỏe và IoT. Redis là một lựa chọn phổ biến cho caching, session management, gaming, leaderboards và hệ thống real-time.

Tóm gọn lại, Redis là một cache. Nó cho phép chúng ta cache thông tin  lên dưới dạng key-value. Và tiếp theo đây, chúng ta sẽ cùng tìm hiểu cách caching trong Java với Redis.

>>> Xem thêm bài viết:

- Alert manager: Cấu hình cảnh báo bằng Prometheus cho hệ thống K8s

- Monitoring trên K8s cluster với Prometheus và Grafana

- Hướng dẫn cài đặt Web server Apache trên CentOS 7

3. Caching trong Java với Redis

Tất nhiên để có thể implement cache với Redis thì chúng ta sẽ cần có Jdk và Redis rồi. Trong khuôn khổ bài này, chúng ta sẽ không đi sâu vào tìm hiểu cách cài đặt Redis, các bạn có thể tìm hiểu cách cài đặt Redis từ các nguồn Internet bởi nó không hề khó.

Sau khi đã hoàn thành việc chuẩn bị cài đặt, chúng ta sẽ bắt đầu thao tác cache trên Redis với Java nhé.

3.1. Redisson

Redisson là một bộ thư viện Java cho phép chúng ta có thể thao tác với Redis, nó được viết trên nền thư viện non-blocking I/O rất nổi tiếng đó là Netty. 

Bạn có thể copy dependency dưới đây cho project gradle của mình. Cú pháp:

implementation group: 'org.redisson', name: 'redisson', version: ‘3.14.1’

3.2. Thao tác với Redisson

Để sử dụng Redisson, chúng ta cần khởi tạo một RedissonClient và dùng nó như một client redis-cli để set và get các giá trị trong Redis. Dưới đây là một ví dụ về cách sử dụng file cấu hình các thông tin kết nối tới Redis và sử dụng nó để tạo một RedissonClient.

public static RedissonClient init() {
    try {
        Config config = org.redisson.config.Config.fromJSON(new File("./redis-config.json"));
        return Redisson.create(config);
    } catch (Exception ex) {
        LOGGER.error(ex, ex);
        return null;
    }
}

Một file cấu hình Redisson:

{
  "singleServerConfig" : {
    "address": "redis://120.0.0.1:6379"
  }
}

Sau khi đã có đối tượng RedissonClient, chúng ta có thể ghi và đọc cache như sau:

public void set(String key, String value, int timeout, TimeUnit timeUnit) {
    try {
        RBucket<String> bucket = redisson.getBucket(key);
        if (timeout > 0) {
            bucket.set(value, timeout, timeUnit);
        } else {
            bucket.set(value);
        }
        LOGGER.info("Set value to key ----- {}", key);
    } catch (Exception ex) {
        LOGGER.error("Set value {} to key {} error ", value, key, ex);
    }
}
public <T> RBucket<T> get(String key, Class<T> clazz) {
    try {
        return redisson.getBucket(key);
    } catch (Exception ex) {
        LOGGER.error("Get generic bucket, class {} from key {} error ", clazz, key, ex);
    }
    return null;
}

Kết bài

Caching là một chủ đề không hề mới, tuy nhiên nó lại rất hữu dụng trong công việc hàng ngày của các lập trình viên. Có thể thấy, cache tồn tại trong hầu hết các phần mềm mà chúng ta sử dụng hàng ngày, từ các trình duyệt, các ứng dụng chat hay sâu xa hơn mà chúng ta không biết đó là các web server, proxy. Qua bài viết này, Stringee mong các bạn đã hiểu thêm nhiều về cache cũng như cách để sử dụng nó hiệu quả với ngôn ngữ Java.


Stringee Communication APIs là giải pháp cung cấp các tính năng giao tiếp như gọi thoại, gọi video, tin nhắn chat, SMS hay tổng đài CSKH cho phép tích hợp trực tiếp vào ứng dụng/website của doanh nghiệp nhanh chóng. Nhờ đó giúp tiết kiệm đến 80% thời gian và chi phí cho doanh nghiệp bởi thông thường nếu tự phát triển các tính năng này có thể mất từ 1 - 3 năm.

Bộ API giao tiếp của Stringee hiện đang được tin dùng bởi các doanh nghiệp ở mọi quy mô, lĩnh vực ngành nghề như TPBank, VOVBacsi24, VNDirect, Shinhan Finance, Ahamove, Logivan, Homedy,  Adavigo, bTaskee…

Quý bạn đọc quan tâm xin mời đăng ký NHẬN TƯ VẤN TẠI ĐÂY: