预热进度不能只靠日志或info命令,因info返回全局统计、日志缺乏结构化和实时聚合能力;应使用incr+前缀命名空间实现原子计数,按数据类型拆分逻辑单元并隔离存储,配合时间戳埋点与慢日志定位卡点。

预热进度为什么不能只靠日志或 INFO 命令?
因为 INFO 返回的是全局统计(如 keyspace_hits、used_memory_human),无法区分“哪些 key 是预热写入的”;日志又缺乏结构化和实时聚合能力。预热过程一旦卡在某一批数据,你得立刻知道是哪类数据拖慢了整体——比如用户画像比商品信息慢 3 倍,而不是笼统看到“预热耗时 82s”。
用 INCR + 前缀命名空间做轻量级进度计数器
不依赖额外服务,直接利用 Redis 原生命令实现原子计数。关键点在于:把“预热任务”拆成可识别的逻辑单元,并为每个单元维护独立计数器。
- 预热启动时,用
SET warmup:status:start_ts记录开始时间戳,避免重启后状态丢失 - 为每类数据定义固定前缀,例如:
warmup:users:total、warmup:users:done、warmup:products:total、warmup:products:done - 每成功写入一个用户缓存,执行
INCR warmup:users:done;写入前先INCR warmup:users:total(或批量预设总数) - 客户端轮询时,用
MGET warmup:users:done warmup:users:total warmup:products:done warmup:products:total一次性拉取,减少往返开销
如何避免计数器本身成为瓶颈或误差源?
高并发预热时,多个线程/协程同时 INCR 同一个 key 是安全的,但若用 GET + SET 模拟计数,就会丢数据。另外,别把计数器和业务 key 混放——否则 KEYS warmup:* 可能干扰线上扫描逻辑。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 所有预热计数器统一放在专用 DB(如
SELECT 15),与业务缓存物理隔离 - 不依赖
KEYS做动态发现,改用硬编码的 key 列表或配置中心下发,防止扫描阻塞 - 如果预热中途失败,用
GET warmup:users:done和数据库实际条数比对,快速定位断点,而非重跑全量 - 注意
INCR返回值是字符串,客户端需转整型;某些旧版 Jedis 默认返回 byte[],容易误判为空
配合 MONITOR 或慢日志定位卡点是否必要?
没必要常态化开启 MONITOR——它会吃掉 30%+ 性能,且输出无结构。真正需要的是“在预热脚本里埋点”:
- 每个大类数据预热前后打时间戳,写入
SET warmup:users:phase1_start 1716976440和SET warmup:users:phase1_end 1716976452 - 用
EXPIRE warmup:users:phase1_start 3600自动清理过期元数据,避免残留 - 当发现
warmup:users:done长时间不更新,直接查slowlog get 5,看最近 5 条慢命令是否集中在某条HSET或PIPELINE批量写
进度监控的本质不是“显示数字”,而是让异常可定位、可回溯。计数器只是入口,背后必须连着明确的阶段划分和可观测锚点。










