String approach: serialize toàn bộ object thành JSON và lưu vào một key — đơn giản, một GET là lấy toàn bộ.
- Nhược điểm: muốn update một field phải GET toàn bộ object, deserialize, update, serialize lại, SET — tốn băng thông và CPU; race condition nếu concurrent write. Hash approach: mỗi field là một Hash field —
HSET user:1 name 'Alice' age 30 email 'a@b.com';HGET user:1 namelấy một field;HINCRBY user:1 age 1tăng atomic không cần GET. Memory trade-off: Redis tự dùnglistpackencoding (compact array, đổi tên từ ziplist trong Redis 7.0) khi Hash nhỏ (<hash-max-listpack-entries=128field vàhash-max-listpack-value=64bytes) — hash nhỏ tốn ít memory hơn nhiều String key riêng lẻ. - Khi vượt ngưỡng, Redis chuyển sang
hashtableencoding. Quyết định: nhiều field thay đổi độc lập → Hash; object luôn đọc/ghi toàn bộ → String (JSON); object rất lớn (> 1KB serialized) → String với compression.
String approach: serialize the entire object as JSON into a single key — simple, one GET retrieves everything.
- Drawback: updating a single field requires GET the full object, deserialize, update, serialize, and SET — wastes bandwidth and CPU; race conditions with concurrent writes. Hash approach: each field is a Hash field —
HSET user:1 name 'Alice' age 30 email 'a@b.com';HGET user:1 namefetches one field;HINCRBY user:1 age 1increments atomically without a GET. Memory trade-off: Redis automatically useslistpackencoding (a compact array, renamed from ziplist in Redis 7.0) for small Hashes (<hash-max-listpack-entries=128fields andhash-max-listpack-value=64bytes) — a small Hash uses much less memory than many individual String keys. - When these thresholds are exceeded, Redis switches to
hashtableencoding. Decision rule: many fields updated independently → Hash; object always read/written as a whole → String (JSON); very large objects (> 1KB serialized) → String with compression.