Chọn Cấu Trúc Phù Hợp
Cấu trúc dữ liệu Redis đơn giản — không cái nào có khả năng là sự khớp hoàn hảo cho vấn đề bạn đang cố giải quyết. Nhưng nếu bạn chọn cấu trúc ban đầu đúng cho dữ liệu của bạn, các lệnh Redis có thể hướng dẫn bạn đến các cách hiệu quả để lấy những gì bạn cần. Nhiều lệnh Redis có tiền tố (prefix) chỉ ra kiểu cấu trúc dữ liệu bên dưới chúng được thiết kế để làm việc.
Cấu Trúc Dữ Liệu Chung
| Prefix | Cách Dùng | Lưu Ý Và Lỗi Thường Gặp | |
|---|---|---|---|
| Hash | H | Lưu trữ object; bất cứ thứ gì bạn dùng dictionary object cho | Giống như chính Redis, một trong những vấn đề lớn nhất người dùng gặp với Hash là kế toán key. Hãy chắc chắn bạn có hệ thống để đảm bảo bạn không lấp đầy hash với key và value không cần thiết. |
| List | L | Hàng đợi (queue), stack, và list vòng (cyclical lists) | Đừng cố truy cập ngẫu nhiên (random access) trên list lớn, và cẩn thận về queue bị backup. |
| Set | S | Hệ thống tagging, bucket cho dữ liệu time-series | Phép giao (intersection) và hợp (union) phải dùng cẩn thận - giữ set nhỏ. Set không phải cách tốt nhất để đếm unique. Dùng HyperLogLog thay vào đó! |
| Sorted Set | Z | Bảng xếp hạng (scoreboard), tìm kiếm từ điển (lexicographical), list truy cập ngẫu nhiên | Zsets là một trong những cấu trúc linh hoạt nhất, và cũng là một trong những cái đắt nhất. Giữ mắt chăm chăm vào big O của bạn! Nếu bạn dùng sorted set cho autocomplete, bạn có thể điều tra ZRANGEBYLEX, xử lý tìm kiếm từ điển (nhưng cẩn thận với UTF-8!) |
| Stream | X | Time series, queue, phân phối tin nhắn | Quên giới hạn (cap) streams là phổ biến, chúng cũng đôi khi bị nhầm lẫn với khả năng của hệ thống nhắn tin phân tán (cụ thể Apache Kafka). |
| String | (không có) | Cache đơn giản, counter, thao tác bit | Cẩn thận về giá trị cực lớn, GET/SET của chúng có thể gây ra lỗi khó tìm trong một số network và Redis client. Dễ dàng tự hại mình bằng cách dùng SETNX xây dựng hệ thống locking. |
Cấu Trúc Dữ Liệu Chuyên Biệt
Redis cung cấp một số thao tác để thao tác các trường hợp đặc biệt của các kiểu cụ thể, trong khi kiểu "bên dưới" là một trong các kiểu dữ liệu chung ở trên:
| Prefix | Kiểu Gốc | Cách Dùng | Lưu Ý Và Lỗi Thường Gặp | |
|---|---|---|---|---|
| Bitmap | BIT | String | Flag tiết kiệm không gian cho analytics | Nhầm lẫn về khả năng, hoặc mất kiểm soát độ phức tạp kế toán trong hệ thống dựa trên bitmap. |
| Counter | INCR, DECR | String | Analytics tiết kiệm không gian | Tràn phạm vi signed 64-bit sẽ trả về lỗi |
| Geohash | GEO | Sorted Set | Lưu locator, tìm user gần bằng | Tính toán khoảng cách xa, bất kỳ đâu cần projection chuyên biệt hoặc hàm địa lý phức tạp. |
| HyperLogLog | PF | String | Đếm unique cho analytics | Gộp nhiều HLL lại với nhau có thể tốn kém. Hãy chắc chắn có giới hạn (cap) cho số lượng tham số bạn chỉ định trong PFMERGE. |
| Pub/Sub | PUB, SUB, PSUB | (không có) | Truyền tin nhắn phù du | Đơn giản, nhanh, message-passing không có durability. Kiểu Stream là lựa chọn tốt hơn cho hầu hết trường hợp sử dụng. |
Sử Dụng Big O
Lạm dụng mẫu truy cập của cấu trúc dữ liệu giống như lạm dụng từ điển: đừng lật từng trang để tra từ! Độ phức tạp thời gian của mọi lệnh Redis được tài liệu hóa trên redis.io.
Big O là cách biểu diễn "hành vi giới hạn" (limiting behavior) cho cách một thứ sẽ thực hiện. Một cách đơn giản để nghĩ về nó là phép toán sẽ thực hiện như thế nào khi lượng dữ liệu trong hệ thống tăng. Nếu một phép toán là O(1), nó sẽ mất một lượng thời gian cố định để hoàn thành, không quan tâm bao nhiêu dữ liệu liên quan. Một phép toán O(n) sẽ scale tuyến tính với dữ liệu, và cái nào O(n²) trở nên chậm hơn theo cấp số nhân khi lượng dữ liệu tăng.
Để điều trị kỹ hơn, xem giới thiệu dễ dàng về big O với code mẫu và đồ thị.
Thiết kế hệ thống tốt đòi hỏi hơn phân tích thuật toán cơ bản, nhưng đáng giá để ôn tập lại cơ bản theo thời gian, và suy nghĩ về tổng độ phức tạp truy cập dữ liệu trong app của bạn.
Giữ Các Phép Toán Nhỏ
Redis là single-threaded, điều này làm cho nó dễ reasoning (suy luận) nhưng cũng có thể gây bất ngờ cho những người chỉ quen với truy cập dữ liệu multi-threaded. Phép toán chạy lâu (long-running operations) nguy hiểm hơn trong Redis hơn trong database khác: vì Redis chỉ làm một việc tại một thời điểm, phép toán chạy lâu có thể gây backup hệ thống toàn bộ.
Giữ các thao tác truy cập dữ liệu rất chi tiết (granular) là chìa khóa cho hiệu suất tốt với Redis. 100.000 phép toán O(1) trong Redis có thể ưu việt hơn 1 phép toán O(N) trên collection 100.000 phần tử, ngay cả khi bạn phải trả giá do network và protocol parsing.
Làm sao tìm ra điểm đau (pain-point) trong hệ thống của bạn? Kiểm tra SLOWLOG thường xuyên (hoặc nếu bạn là khách hàng RedisGreen, chỉ cần xem tab "Slow Queries" trên dashboard). Càng lâu một phép toán đơn lẻ chạy, càng làm chậm mọi thứ khác hệ thống của bạn đang cố làm, vì vậy hãy giữ nó ngắn!