Hash结构Field数量膨胀会导致大Key问题,单个cart:user:123 Key下存几百个商品时,HGETALL响应时间可能从毫秒级升至几十毫秒,Redis主线程阻塞风险上升;需按SKU拆分、设硬上限、禁用HGETALL全量拉取。

Hash结构的Field数量膨胀会导致大Key问题
单个cart:user:123 Key下存几百个商品时,HGETALL响应时间可能从毫秒级升至几十毫秒,Redis主线程阻塞风险上升。这不是理论风险——线上监控显示,Field超500后,平均延迟跳变明显。
避免方式:
• 按SKU维度拆分:用cart:user:123:sku:1001 + cart:user:123:meta分离基础信息与元数据
• 设置硬上限:在addToCart逻辑里加hlen校验,超300个Field时触发归档或告警
• 禁止用HGETALL全量拉取:前端分页请求时,只用HSCAN配合count=20流式获取
JSON序列化Value带来的CPU和内存开销
把整个CartItem对象转成JSON字符串存进Hash的Value,看似方便,但每次HGET都要反序列化,QPS上万时GC压力陡增;同时JSON字符串比二进制紧凑格式多占30%~50%内存。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
更优做法:
• 用StringRedisTemplate + Gson时,启用GsonBuilder().serializeNulls().disableHtmlEscaping()
• 对高频字段(如quantity、selected)单独提为Hash Field,例如cart:user:123:qty:1001,避免解析整段JSON
• 若用RedisTemplate泛型,务必指定valueSerializer为Jackson2JsonRedisSerializer而非默认JdkSerializationRedisSerializer(后者序列化体积大、兼容性差)
未登录用户购物车合并引发的并发写冲突
用户从“临时会话”登录后,需把cart:session:abc123合并到cart:user:456。若两个请求同时触发合并,可能出现商品数量翻倍或覆盖——因为HGETALL + HSET不是原子操作。
安全合并必须满足:
• 合并前对目标Key加分布式锁(SET cart:user:456:merge_lock "1" NX EX 10)
• 使用EVAL脚本执行原子合并:遍历源Hash所有Field,用HINCRBY累加数量,再DEL源Key
• 合并失败时降级为客户端重试,而非静默丢弃
过期策略误配导致购物车“意外消失”
给cart:user:123设固定TTL(比如7天),看起来合理,但实际中用户可能连续活跃——结果刚加完商品,缓存就过期了。更隐蔽的问题是:用EXPIRE手动设置过期,但没在每次HSET后刷新TTL,导致长期不操作的购物车提前失效。
正确做法:
• 放弃全局TTL,改用“滑动过期”:每次读写都执行EXPIRE cart:user:123 604800
• 对未登录用户Key(cart:session:xxx)用短TTL(30分钟),登录后迁移到长生命周期Key
• 在clear()操作里显式DEL + EXPIRE双保险,防止残留Key占用内存
HSCAN游标管理与EXPIRE时机——它们不报错,但会在高负载时突然拖慢整个Redis实例。


















