Redis Hash 類型:對象存儲的最佳選擇
Redis Hash 是 Field-Value 鍵值對集合,底層採用「小哈希表」優化內存:字段較少時使用 Zipmap(非哈希表,節省元數據),字段/值超過閾值自動轉為標準哈希表。新增、刪除、查找平均 O(1),極適合存儲對象(如用戶信息、商品詳情)。
1. 內存優化機制
hash-max-ziplist-entries 512:字段數超過 512 轉標準哈希。
hash-max-ziplist-value 64:單字段值超過 64 字節轉標準哈希。
- Zipmap 雖為 O(N) 操作,但對象字段通常較少,實際性能極高。
2. 核心命令速查表
| 命令 | 作用 | 時間複雜度 | 示例 |
| HSET key field value | 設置單字段 | O(1) | HSET user:1 name "Alice" |
| HSETNX key field value | 字段不存在時設置 | O(1) | HSETNX user:1 age 25 |
| HMSET key f1 v1 f2 v2... | 批量設置 | O(N) | HMSET user:1 name "Bob" age 30 |
| HGET key field | 獲取單字段 | O(1) | HGET user:1 name |
| HMGET key f1 f2... | 批量獲取 | O(N) | HMGET user:1 name age |
| HEXISTS key field | 判斷字段是否存在 | O(1) | HEXISTS user:1 email |
| HDEL key f1 [f2...] | 刪除字段 | O(N) | HDEL user:1 age |
| HKEYS key | 獲取所有字段名 | O(N) | HKEYS user:1 |
| HVALS key | 獲取所有字段值 | O(N) | HVALS user:1 |
| HGETALL key | 獲取所有字段及值 | O(N) | HGETALL user:1 |
| HINCRBY key field incr | 整數增減 | O(1) | HINCRBY stats page_view 1 |
| HINCRBYFLOAT key field incr | 浮點數增減 | O(1) | HINCRBYFLOAT price milk 0.5 |
| HLEN key | 字段數量 | O(1) | HLEN user:1 |
3. 實戰演示
# 存儲用戶對象
HMSET user:1001 username "john" email "john@example.com" age 28 created_at "2023-01-01"
# 獲取部分字段
HMGET user:1001 username email
# 返回: ["john", "john@example.com"]
# 計數器:頁面訪問量
HINCRBY site:stats page_view 1
HINCRBY site:stats unique_visitor 1
# 價格調整(浮點)
HSET product:5001 price 19.99
HINCRBYFLOAT product:5001 price 0.50 # 新價 20.49
# 檢查字段存在
HEXISTS user:1001 phone # 0 不存在
HSET user:1001 phone "13800000000"
HEXISTS user:1001 phone # 1 存在
4. Hash vs String 存儲對象對比
| 維度 | String (JSON 序列化) | Hash (原生) |
| 內存佔用 | 較大(含 JSON 結構字符) | 較小(Zipmap 優化) |
| 局部更新 | 需整體反序列化/序列化 | O(1) 單字段讀寫 |
| 原子操作 | 需 Lua 腳本保證 | HINCRBY 等原子命令 |
| 適用場景 | 整體讀寫、異構系統交互 | 頻繁局部更新、計數器、對象存儲 |
5. 最佳實踐建議
- 對象字段 < 100 且值較小時,Hash 內存優勢明顯。
- 計數器、評分、庫存扣減優先用
HINCRBY/HINCRBYFLOAT 保證原子性。
- 避免單 Hash 字段過多(>5000),導致遷移標準哈希表後內存暴漲。
- Key 設計建議:
object_type:object_id,如 user:1001、product:5001。