
Phát triển ứng dụng với Redis rất thú vị, nhưng như mọi công nghệ, có vài điểm cần lưu ý khi thiết kế ứng dụng dựa trên Redis hoặc Redis namespace. Bạn có thể đã quen với phát triển database quan hệ, nhưng dù nhiều thực hành tương tự áp dụng, hãy nhớ Redis là database in-memory và nó (chủ yếu) single-threaded. Đọc tiếp để khám phá best practices cho Redis keys.
Do đó, có một số đặc thù bạn nên chú ý khi dùng Redis:
1. Theo Dõi Key Với Redis Namespace
Database lưu dữ liệu, nhưng bất kỳ dev nào cũng có thể mất kiểm soát một số dữ liệu bạn đưa vào Redis. Điều này tự nhiên, do yêu cầu ứng dụng thay đổi hoặc bạn thay đổi cách lưu trữ. Có thể bạn quên EXPIRE một số key, hoặc một module ứng dụng đã bị loại bỏ.
Dù trường hợp nào, có khả năng một số dữ liệu trong database Redis không còn dùng và chiếm chỗ vô ích. Bản chất schema-less của Redis khiến rất khó hiểu nội dung dataset trừ khi bạn dùng nomenclature (phép đặt tên) chắc chắn cho key. Dùng phương pháp đặt tên đúng với Redis namespace cho key – quy ước dùng dấu hai chấm (:) để phân tách các phần tên key – là best practice của Redis namespace. Cách này, bạn dễ dàng nhận diện chúng trong migration, chuyển đổi, xóa, hoặc di chuyển dữ liệu. Redis namespace & Redis namespace keys giúp nhận diện này.
Ngoài Redis namespace, use case phổ biến khác của Redis là làm secondary data store cho dữ liệu "hot", trong khi hầu hết dữ liệu nằm ở database khác (ví dụ PostgreSQL, MongoDB). Trong trường hợp này, dev thường quên xóa dữ liệu khỏi Redis khi nó được di chuyển khỏi primary data store. Phụ thuộc cross-datastore này yêu cầu cascading delete, có thể triển khai bằng cách giữ tất cả identifier cho một data item trong một Redis set. Điều này đảm bảo quy trình dọn dẹp sau xóa khỏi primary data store chỉ cần lặp qua nội dung set đó để xóa tất cả bản sao liên quan và mảnh vụn (kể cả chính set khi hoàn tất).
2. Theo Dõi Độ Dài Tên Key
Điều này có vẻ trái ngược với trên về Redis namespace, nhưng vì tên key cũng chiếm bộ nhớ, bạn nên cố gắng giữ chúng ngắn. Rõ ràng đây là vấn đề với dataset hàng triệu hoặc tỉ key, nhưng sự thật là key dài có chi phí với bất kỳ hashtable nào.
Ví dụ: lưu 1.000.000 key với Redis namespace, mỗi key set giá trị 32 ký tự, sẽ tốn khoảng 96MB với tên key 6 ký tự, và 111MB với tên 12 ký tự (trên Redis server 32-bit). Overhead hơn 15% này trở nên đáng kể khi số key tăng. Với Redis, xóa key theo prefix cũng là khả thi.
3. Dùng Cấu Trúc Dữ Liệu Đúng
Dù vì sử dụng bộ nhớ hay hiệu suất, đôi khi một cấu trúc dữ liệu phù hợp dataset hơn cái khác. Dưới đây là một vài best practices:
Thay vì lưu dữ liệu trong hàng nghìn (hoặc triệu) giá trị string độc lập, cân nhắc gom dữ liệu liên quan với cấu trúc hash. Hash rất hiệu quả và có thể giảm sử dụng bộ nhớ (cùng cung cấp giá trị thêm: trừu tượng hóa một số chi tiết và làm code dễ đọc hơn). Xem bài này để biết thêm.
Khi phù hợp, dùng list thay vì set. Nếu không cần thuộc tính set đảm bảo duy nhất hoặc kiểm tra thành viên, list tiêu ít bộ nhớ hơn và insert nhanh hơn.
Sorted set là cấu trúc tốn kém nhất, cả về tiêu thụ bộ nhớ và độ phức tạp thao tác cơ bản (ví dụ ZADD thành viên mới). Nếu chỉ cần tra điểm (score) và thứ tự không quan trọng, cân nhắc dùng hash thay thế.
Tính năng thường bị bỏ qua trong Redis là bitmap, hoặc bitset (có từ v2.2). Bitset cho phép thực hiện vài thao tác bit-level trên giá trị Redis, có nghĩa là lưu lượng lớn dữ liệu hiệu quả. Có thể dùng, ví dụ, cho analytics nhẹ.
4. Dùng SCAN, Không Bao Giờ Dùng KEYS
Lệnh SCAN có từ Redis v2.8 cho phép lấy key trong keyspace dùng con trỏ (cursor). Hành vi này khác với lệnh KEYS (hiss), trả về tất cả phần tử khớp cùng lúc, nhưng coi là rủi ro trong production vì có thể block server Redis và thậm chí cạn kiệt RAM. SCAN, ngược lại, cho phép kiểm tra dữ liệu mà không rủi ro block server hoặc phải تعتمد vào slave.
Lưu ý SCAN yêu cầu đọc giá trị cursor truyền cho lần gọi SCAN tiếp theo. SCAN cũng chấp nhận pattern tên key và đối số count tùy chọn. Khác biệt khác: có thể lấy cùng tên key nhiều hơn một lần với SCAN.
SCAN đi kèm SSCAN, HSCAN, và ZSCAN, cho phép lặp nội dung set, hash, và sorted set (theo thứ tự).
5. Dùng Lua Script Côté Server (Server-Side Lua Scripts)
Là dev, bạn sẽ trên địa bàn quen thuộc khi chấp nhận khả năng chạy Lua script của Redis. Một trong những ngôn ngữ dễ học nhất, Lua cho bạn khả năng thể hiện sáng tạo với code chạy bên trong chính server Redis. Khi áp dụng đúng, Lua script có thể tạo khác biệt to lớn về hiệu suất và tiêu thụ tài nguyên. Thay vì đưa dữ liệu đến CPU (của ứng dụng), script cho phép thực thi logic gần dữ liệu, giảm độ trễ mạng và truyền dữ liệu dư thừa.
Ví dụ kinh điển của tác động mạnh Lua: khi bạn lấy nhiều dữ liệu từ Redis chỉ để lọc hoặc tổng hợp trong ứng dụng. Bằng cách đóng gói quy trình xử lý trong script, bạn chỉ cần invoke nó để nhận câu trả lời nhỏ hơn nhiều trong thời gian và tài nguyên nhỏ hơn nhiều.
Pro Tip: Lua tuyệt vời, nhưng khi chuyển workflow vào nó bạn có thể thấy báo lỗi và xử lý khó hơn (bạn chạy bên trong server Redis). Một cách khéo léo giải quyết: dùng Pub/Sub của Redis và cho script publish "log" message vào kênh chuyên dụng. Sau đó thiết lập subscriber process nhận message và xử lý tương ứng.
Có thể nhiều tip quan trọng khác bạn sẽ học được trong hành trình Redis, nhưng danh sách này giúp bắt đầu với những điều quan trọng nhất. Nếu bạn có gợi ý khác, feedback hoặc câu hỏi – thoải mái liên hệ, tôi luôn available 🙂