Redis Hash
→ 返回 Redis
Hash 将单个 key 映射为多个 field → value,适合表示对象属性(用户资料、商品 SKU 属性、购物车行)。等价于「一个 key 下的小字典」,比把整个对象 JSON 塞进 String 更便于按字段读写与 HINCRBY 原子加减。
完整命令表见 基础命令 · Hash。
HSET user:1001 name Alice age 30 points 100
HGET user:1001 name
HINCRBY user:1001 points 10
HSCAN user:1001 0 COUNT 20底层编码
| 条件 | 编码 | 说明 |
|---|---|---|
| 字段少、值短 | listpack(旧版 ziplist) | 内存紧凑 |
| 字段多或值长 | hashtable | 标准哈希表 |
阈值随 hash-max-listpack-entries / hash-max-listpack-value 配置变化。字段从 10 个涨到 5000 会触发编码升级,可能短暂阻塞。
典型场景
| 场景 | Key 示例 | 设计要点 | |
|---|---|---|---|
| 用户缓存 | user:{id} | field = 属性名;TTL 设在整个 key | |
| 购物车 | cart:{userId} | field = skuId,value = 数量;HINCRBY 改数量 | |
| 会话 | session:{token} | 多字段存登录态,替代大 String JSON | |
| 计数分组 | stats:20240601 | field = 渠道/类型,value = 计数 | |
| 步数(按日) | step:20240601:{uid} | 单 field 或 String 亦可,见 排行榜与实时计数 |
Hash vs String(JSON)
| 维度 | Hash | String + JSON |
|---|---|---|
| 改一个字段 | HSET / HGET O(1) | 读改写整段 JSON |
| 部分读取 | 原生支持 | 需反序列化 |
| 嵌套结构 | 扁平 field,或 value 再 JSON | 一层 JSON 更自然 |
| 内存 | 多 field 有元数据 | 单 blob 可能更省 |
分布式与集群注意
- 整个 Hash 落在一个 key 的一个 slot(Cluster),不会按 field 分片。
- 热 key:超大 Hash(百万 field)打在同一节点 → 用分片 key(
cart:{uid}:0…cart:{uid}:N)或改模型。 - 禁止在生产对巨大 Hash 用
HGETALL、KEYS— 阻塞单线程,见 Redis。
与 ZSet 的配合
- 排行榜用 ZSet(score 排序);Hash 存用户展示信息(
user:{id}),榜只存 id + 分数,查榜后再HMGET批量补全昵称头像。
Spring Boot
redisTemplate.opsForHash().put("user:1001", "name", "张三");
redisTemplate.opsForHash().increment("user:1001", "points", 10L);
Map<Object, Object> map = redisTemplate.opsForHash().entries("user:1001");详见 Redis 集成。