Redis哈希
哈希(Hash)是一个键值对集合,适合存储对象结构数据,如用户信息、商品属性等。
结构概述
基本特点
Bash
- 键值对集合,一个Hash包含多个field-value
- 适合存储对象结构
- 类似Java的Map、Python的dict
- 单个Hash最多2^32-1个字段
结构示意
Bash
key: user:1000
├── field: name → value: "Alice"
├── field: age → value: "25"
├── field: city → value: "Beijing"
└── field: email → value: "alice@example.com"
内部编码
ziplist编码
Bash
触发条件:
- 字段数量 ≤ hash-max-ziplist-entries(默认512)
- 所有value长度 ≤ hash-max-ziplist-value(默认64)
特点:
- 紧凑连续内存
- 内存效率高
- 顺序存储field-value
- 适合小规模数据
hashtable编码
Bash
触发条件:
- 字段数量 > 512
- 或value长度 > 64字节
特点:
- 标准哈希表结构
- 字典实现
- O(1)查找效率
- 内存占用较大
查看编码
Bash
HSET user:1000 name "Alice" age 25
OBJECT ENCODING user:1000
# 返回: "ziplist"
HSET big:hash field1 "very long value exceeding 64 bytes..."
OBJECT ENCODING big:hash
# 返回: "hashtable"
编码转换
转换规则
Bash
# 配置阈值
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
# 超过阈值自动转换
ziplist → hashtable
# 转换不可逆
转换示例
Bash
# 添加超过512个字段
for i in {1..513}; do
HSET large:hash field$i "value$i"
done
OBJECT ENCODING large:hash
# 返回: "hashtable"
应用场景
1. 用户信息存储
Bash
# 存储用户对象
HSET user:1000 name "Alice" age 25 city "Beijing" email "alice@example.com"
# 获取单个字段
HGET user:1000 name
# 获取多个字段
HMGET user:1000 name age city
# 获取全部信息
HGETALL user:1000
# 更新字段
HSET user:1000 age 26
2. 商品属性存储
Bash
# 存储商品属性
HSET product:1001 name "iPhone" price "999" stock "100" category "phone"
# 查询价格
HGET product:1001 price
# 库存增加
HINCRBY product:1001 stock -1
3. 购物车
Bash
# 添加商品到购物车
HSET cart:user:1000 product:1001 2 product:1002 1
# 获取购物车
HGETALL cart:user:1000
# 更新数量
HINCRBY cart:user:1000 product:1001 1
# 移除商品
HDEL cart:user:1000 product:1002
4. 配置信息
text
# 存储系统配置
HSET config:system timeout 30 maxconn 1000 mode "production"
# 获取配置
HGET config:system timeout
# 更新配置
HSET config:system timeout 60
与String对比
存储对象对比
text
# 方式1:String存储JSON
SET user:1000 '{"name":"Alice","age":25,"city":"Beijing"}'
GET user:1000
# 更新需读取-修改-写入
# 方式2:Hash存储对象
HSET user:1000 name "Alice" age 25 city "Beijing"
HGET user:1000 name
HSET user:1000 age 26
# 单字段更新高效
对比表
| 特性 | String(JSON) | Hash |
|---|---|---|
| 存储格式 | JSON字符串 | field-value |
| 单字段更新 | 低效(全量) | 高效(单字段) |
| 内存占用 | 较小(紧凑) | 可能较大 |
| 部分获取 | 需解析JSON | 直接获取 |
| 适用场景 | 整体读写多 | 部分读写多 |
需频繁更新单字段时用Hash,整体读写用String。
内存优化
ziplist优势
text
- 连续内存,无指针开销
- 字段少时内存效率高
- 配置阈值可调整
优化建议
text
# 调整阈值
hash-max-ziplist-entries 1000 # 增大字段上限
hash-max-ziplist-value 128 # 增大value长度上限
# 延迟转换,保持ziplist编码
字段命名
text
- 使用短字段名:n而非name
- 减少字符串长度
- 节省内存空间
操作特点
O(1)操作
text
HSET/HGET:设置/获取单字段
HDEL:删除字段
HINCRBY:数值增减
HEXISTS:检查存在
HLEN:字段数量
O(N)操作
text
HGETALL:获取全部字段
HKEYS/HVALS:获取全部键或值
HMGET/HMSET:批量操作
# N为字段数量
注意事项
内存转换
text
ziplist转hashtable后内存增加
大量字段时考虑内存开销
可调整阈值控制转换时机
字段数量
text
# 大量字段时HGETALL性能下降
# 建议使用HSCAN遍历
HSCAN large:hash 0
哈希冲突
text
hashtable编码下存在哈希冲突
Redis采用链地址法解决
渐进式rehash扩容
编码对比
| 编码 | 条件 | 内存效率 | 查找效率 | 适用场景 |
|---|---|---|---|---|
| ziplist | ≤512字段且≤64字节 | 高 | O(N) | 小对象 |
| hashtable | >512字段或>64字节 | 中 | O(1) | 大对象 |
要点总结
- 哈希适合存储对象结构,一个key下多个field-value
- ziplist编码适合小数据(≤512字段,≤64字节value)
- hashtable编码适合大数据,O(1)查找
- 单字段更新用Hash比String(JSON)更高效
- 应用场景:用户信息、商品属性、购物车、配置信息
- HINCRBY原子增减数值,适合计数统计
- 大量字段时使用HSCAN遍历,避免HGETALL阻塞
- 调整hash-max-ziplist-entries/value可优化内存
📝 发现内容有误?点击此处直接编辑