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 后,过期时间会分散到各桶,整键级的过期需要业务层自己维护。