首页/数据/Redis 进阶速查/HGETALL 大 hash 的读法
性能与排障129 条

HGETALL 大 hash 的读法

大 hash 上用 HGETALL 会一次性返回全部字段并占用输出缓冲;改造方向:HSCAN 分页、按业务拆分小 hash、只取需要字段的 HMGET。

Redis 进阶速查数据更新于 2026-10-13

HGETALL 与大 hash

HGETALL 一次返回哈希的全部字段与值,返回体量随字段数线性增长。字段数上千以后,单次调用会同时占用服务端输出缓冲与客户端内存;在 Redis 逐条执行的模型下,这次调用的处理时间也被拉长。要全量遍历用 HSCAN 做游标式分页,只取需要的字段用 HMGET。

基本信息

命令原型HGETALL key
复杂度O(N),N 为字段数
返回字段与值交替的扁平数组
分页替代HSCAN cursor COUNT n
定向替代HMGET key field ...
版本HSCAN 需 Redis 2.8 及以上

典型使用场景

  • 配置、画像类 hash 字段膨胀到数千,管理端页面仍按全量渲染
  • 缓存预热或数据校对时需要抽样查看整键内容
  • 排查字段命名、脏数据等是否符合预期
  • 多数调用方其实只用少数几个字段,没必要拉全量
  • 拆分大键或迁移结构之前的现状盘点

从粗到细的读法

从粗到细的读法
redis-cli HLEN big:hash                  # 先看字段总量,判断是否算大键
redis-cli HGETALL big:hash | head -40    # 只想瞄一眼时,取前若干行抽样
redis-cli HSCAN big:hash 0 COUNT 200     # 游标分页,每次约 200 个字段
redis-cli HSCAN big:hash 0 COUNT 200 MATCH 'cfg:*'   # 按字段名模式过滤
redis-cli HMGET big:hash f1 f2 f3        # 定向取字段,返回体量可控
redis-cli MEMORY USAGE big:hash          # 单键内存占用,为拆分方案定量

返回项读法

返回项含义读法
HSCAN 首个返回下次遍历的游标为 0 表示遍历已结束,不是表示没数据
HSCAN 第二个返回字段与值交替的数组COUNT 只是提示,实际条数可多可少
HGETALL 返回完整扁平数组字段越多,客户端解析也越吃内存
HLEN字段总数判断是否属于大键的第一手数据
MEMORY USAGE键与值的估算字节数为拆桶方案提供定量依据
COUNT 不保证每次返回该数量;在字典 rehash 期间,HSCAN 可能返回重复字段或漏掉个别字段,遍历逻辑按幂等处理即可。
对在线大 hash 直接 HGETALL,输出缓冲可能顶到 client-output-buffer-limit 导致连接被服务端断开;管理端展示不应走全量读。
按 id 取模把大 hash 拆成多个小 hash 后,过期时间会分散到各桶,整键级的过期需要业务层自己维护。

易错点

  • 对大 hash 用 HGETALL 遍历:服务端输出缓冲与客户端内存同时上涨,连接可能被输出缓冲上限断开,改 HSCAN 分页即可
  • 拿 HGETALL 的返回为空来判键是否存在:空 hash 会被自动清理,键不存在与字段为空是两种语义
  • HSCAN 遍历期间字段被增删:语义是弱一致,可能重复或遗漏,调用方要能容忍
  • 拆分小 hash 只按取模分桶而不设计整键过期,残留数据会长期占内存

数据来源与参考

  • Redis 官方文档:HSCAN 与 hash 访问
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌