当前位置: 首页 > news >正文

Redis命令-Hash命令

一、前言:为什么用 Hash 存储对象?

在 Redis 中,Hash(哈希)是一种非常高效的键值对集合类型,特别适合存储对象

例如:

  • 用户信息:user:1001 → {name: "Alice", age: 25, email: "a@example.com"}
  • 商品详情:product:2001 → {title: "手机", price: 2999, stock: 100}

相比将每个字段拆成独立 key(如user:1001:nameuser:1001:age),Hash 具有:
内存更省(Redis 对小 Hash 有特殊编码优化)
操作原子性(单个 Hash 内部操作是原子的)
网络开销更低(一次命令获取多个字段)

本文将系统讲解Redis Hash 的所有核心命令,并附带实战示例与最佳实践


二、Hash 核心命令速查表

命令作用时间复杂度
HSET key field value [field value ...]设置一个或多个字段O(1) 每个字段
HGET key field获取指定字段的值O(1)
HMSET key field value [field value ...]已废弃,用HSET替代
HMGET key field [field ...]获取多个字段的值O(N),N=字段数
HGETALL key获取所有字段和值O(N),N=字段数
HDEL key field [field ...]删除一个或多个字段O(N),N=字段数
HEXISTS key field判断字段是否存在O(1)
HLEN key获取 Hash 字段数量O(1)
HKEYS key获取所有字段名O(N)
HVALS key获取所有字段值O(N)
HINCRBY key field increment对整数值字段加减O(1)
HINCRBYFLOAT key field increment对浮点值字段加减O(1)
HSTRLEN key field获取字段值的字符串长度O(1)

💡注意:从 Redis 4.0 起,HMSET被标记为 deprecated,统一使用HSET


三、常用命令详解与示例

3.1 写入数据:HSET

# 设置单个字段 127.0.0.1:6379> HSET user:1001 name "Alice" (integer) 1 # 1=新增,0=更新 # 设置多个字段(推荐!) 127.0.0.1:6379> HSET user:1001 age 25 email "alice@example.com" city "Beijing" (integer) 3 # 新增了 3 个字段

优势:一次命令完成多字段写入,减少网络往返。


3.2 读取数据:HGET/HMGET/HGETALL

# 获取单个字段 127.0.0.1:6379> HGET user:1001 name "Alice" # 获取多个字段(按需加载,避免全量) 127.0.0.1:6379> HMGET user:1001 name age city 1) "Alice" 2) "25" 3) "Beijing" # 获取所有字段(慎用!大数据量会阻塞) 127.0.0.1:6379> HGETALL user:1001 1) "name" 2) "Alice" 3) "age" 4) "25" 5) "email" 6) "alice@example.com" 7) "city" 8) "Beijing"

⚠️生产建议

  • 避免在大 Hash 上使用HGETALL
  • 优先使用HMGET按需获取字段

3.3 删除与判断:HDEL/HEXISTS

# 删除字段 127.0.0.1:6379> HDEL user:1001 email city (integer) 2 # 判断字段是否存在 127.0.0.1:6379> HEXISTS user:1001 email (integer) 0 # 不存在 127.0.0.1:6379> HEXISTS user:1001 name (integer) 1 # 存在

3.4 计数与遍历:HLEN/HKEYS/HVALS

# 字段数量 127.0.0.1:6379> HLEN user:1001 (integer) 2 # 获取所有字段名(调试用) 127.0.0.1:6379> HKEYS user:1001 1) "name" 2) "age" # 获取所有值 127.0.0.1:6379> HVALS user:1001 1) "Alice" 2) "25"

🔍注意HKEYS/HVALS/HGETALL在字段数 > 1000 时可能阻塞主线程!


3.5 数值自增:HINCRBY/HINCRBYFLOAT

# 整数自增(常用于计数器) 127.0.0.1:6379> HSET product:2001 view_count 100 127.0.0.1:6379> HINCRBY product:2001 view_count 1 (integer) 101 # 浮点自增(慎用,精度问题) 127.0.0.1:6379> HINCRBYFLOAT product:2001 avg_score 0.5 "0.5"

典型场景:商品浏览量、用户积分、评分统计。


四、Hash 的内部编码优化

Redis 对小 Hash 使用ziplist(压缩列表)编码,节省内存:

# redis.conf 默认配置 hash-max-ziplist-entries 512 # 字段数 ≤ 512 hash-max-ziplist-value 64 # 每个值长度 ≤ 64 字节

当超过阈值,自动转为hashtable编码。

💡建议

  • 小对象(如用户 profile)非常适合 Hash
  • 大对象(如文章内容)建议用 String 或单独 key

五、实战应用场景

场景 1:用户信息缓存

// Java (Lettuce) redis.hset("user:" + userId, Map.of("name", "Alice", "age", "25", "email", "a@example.com")); String name = redis.hget("user:" + userId, "name"); List<String> fields = redis.hmget("user:" + userId, "name", "age");

场景 2:商品库存与价格

# Python (redis-py) r.hset("product:1001", mapping={ "title": "iPhone 15", "price": "5999", "stock": "50" }) # 扣减库存(Lua 脚本保证原子性) script = """ if tonumber(redis.call('HGET', KEYS[1], 'stock')) >= tonumber(ARGV[1]) then redis.call('HINCRBY', KEYS[1], 'stock', -ARGV[1]) return 1 else return 0 end """ r.eval(script, 1, "product:1001", 1)

场景 3:会话状态管理

HSET session:abc123 user_id 1001 login_time 1700000000 ip "192.168.1.1" HEXPIRE session:abc123 1800 # Redis 7.0+ 支持 Hash 级 TTL

📌注意:Redis 7.0+ 支持HEXPIRE,但早期版本需对整个 key 设 TTL。


六、常见误区与最佳实践

❌ 误区 1:用 Hash 存储超大对象

  • 问题HGETALL阻塞主线程
  • 建议:大对象拆分为多个 key,或使用 String + JSON

❌ 误区 2:频繁使用HGETALL

  • 问题:网络带宽浪费 + 性能下降
  • 建议:明确需要哪些字段,用HMGET

✅ 最佳实践

  1. 字段命名规范:如user_idcreate_time
  2. 避免动态字段爆炸:如HSET log:20250101 ip_192.168.1.1 1(IP 无限)
  3. 监控 Hash 大小:通过HLEN+ 告警防止膨胀

七、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

http://www.jsqmd.com/news/483586/

相关文章:

  • SpringBoot与RocketMQ深度整合:多连接配置与动态Topic处理实战
  • 通过Linux Deploy在旧Android设备上搭建轻量级Linux开发环境
  • WIN10系统解决ST-LINK V2 驱动安装失败数字签名问题
  • TongWeb7在国产操作系统上的安装与配置实战指南
  • 基于N32G430的USB供电参数监测终端设计
  • 2026精选课题-基于springboot美食菜谱分享平台的设计与实现
  • SecGPT-14B开源可部署:提供完整Dockerfile与build.sh,支持离线环境重建镜像
  • 从零到一:基于PyTorch的ResNet34核心实现与梯度消失解析
  • Redis命令-List命令
  • 拇指大小的射频功率计设计与宽量程实现原理
  • 免费IP类API接口全解析:从归属地到行业应用
  • 2026 智能体开发全指南:主流框架盘点、实战代码与选型策略(2026智能体开发系列·第1篇)
  • 探索者STM32F4开发板硬件资源深度解析与实战应用指南
  • GD32 ADC 定时器触发+DMA搬运:构建高效数据采集链的实战指南
  • 地理空间可视化崩溃频发,R 4.5中rgdal弃用后5步无缝迁移至sf+wk+geoarrow(含完整迁移检查清单)
  • 2026精选课题-基于springboot汽车配件管理系统的设计与实现
  • Dify评估引擎升级全景图:从v0.12到v1.5,3类模型判据权重重构、5项延迟优化指标及企业级审计日志规范
  • uniapp集成腾讯播放器实现App端视频播放功能实战
  • 2.1 网络编程 异步网络库zvnet
  • Audio Pixel Studio部署教程(Serverless版):Vercel/Cloudflare Pages托管
  • 别再调戏ChatGPT了!OpenClaw正式“破壳”:那个有手的AI,真的来了
  • DeepSeek-OCR部署避坑:首次唤醒慢问题诊断与SSD缓存优化方案
  • 分离式游戏机硬件平台:GD32F470多模无线交互设计
  • RAG生成阶段优化:解决幻觉、多轮对话与引用标注,小白程序员必备收藏!
  • 从抖振到平滑:基于饱和函数sat(s)的准滑动模态滑模控制SIMULINK实践
  • 第四章 第一性原理 vs 类比思维:人类两种终极思考模式
  • 【常亮24天】立创开源:基于STC32F12K54的低功耗迷你桌面时钟4.0版硬件与软件全解析
  • RockyLinux 10.1深度解析:软重启赋能高效运维,后量子加密守护数据新纪元
  • nlp_gte_sentence-embedding_chinese-large实现Python爬虫数据智能处理:自动化采集与清洗
  • 35岁程序员转型指南:避开年龄危机,拥抱AI高薪新赛道