首页/数据/Redis 进阶速查/小对象聚合:用 hash 摊薄开销
内存与管理99 条

小对象聚合:用 hash 摊薄开销

大量结构相同的小对象可聚合进一个 hash:共享一个键与过期记录,dictEntry 与对象头开销被摊薄,适合画像、设置项类数据。

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

小对象怎么聚

大量结构相同的小对象可以聚合进一个 hash:一个键承载一组字段,共享同一个键名与过期记录,dictEntry 与对象头的固定开销被摊薄。适合画像、设置项这类字段少、数量大、访问模式相近的数据。代价是过期粒度变粗,单键规模要持续盯着。

基本信息

结构形态biz:profile:id 下挂多个字段
收益单对象的固定开销被摊薄
代价过期粒度变粗,整键同生共死
验证方式聚合前后的 MEMORY USAGE 与全局水位对比

典型使用场景

  • 百万级小对象,每个只有几个字段
  • 设置项与开关类配置,字段结构固定
  • 用户画像标签,读写模式相近
  • 键数太多,内存主要花在键与对象开销上
  • 需要按主键整体过期的场景

聚合前后对比

聚合前后对比
redis-cli MEMORY USAGE user:1001:name              # 拆散写法:单键开销示例
redis-cli HSET user:1001 name alice city sh age 30  # 聚合写法,一个键承载多字段
redis-cli HGET user:1001 city                       # 定向读取,不拉全量
redis-cli HMGET user:1001 name age                  # 批量取字段,减少往返
redis-cli MEMORY USAGE user:1001                    # 对比聚合前后的占用
redis-cli INFO memory | grep -E 'used_memory_human' # 全局水位对比

写法与开销对照

写法内存开销读取行为
每字段一个键键名与对象开销重复读取简单,但键数爆炸
单 hash 聚合固定开销被摊薄需 HMGET 定向取,避免 HGETALL
按桶 hash 聚合开销摊薄且单键规模可控需按桶规则计算键名
用 zset 承载偏重排序能力不以省内存为目标
聚合后单键变大,要配合编码阈值评估:hash-max-listpack-entries、hash-max-listpack-value(旧版本为 ziplist 系列参数)。超过阈值后编码从紧凑结构转为哈希表,内存会出现台阶。
聚合粒度不能只按内存算。如果一组字段里有更新很频繁、有几乎不动的,聚合会把热点都压到同一个键上,热点分片的难度随之上升。
聚合方案要定期巡检键规模,否则容易出现把一堆小对象问题换成一个大键问题的情况。

易错点

  • 聚合粒度过大:把小对象问题改造成新的大键问题
  • 字段更新频率差异大:热点字段牵动整键,读写被放大
  • 聚合之后仍用 HGETALL 读取:省下的内存又在内侧被放大回去
  • 忽略编码阈值:超过阈值后内存台阶上升,收益估算失准
  • 聚合后只能整体过期:字段本该有不同生命周期时,要么整体延长要么整体丢弃

数据来源与参考

  • Redis 官方实践:紧凑结构设计
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌