INCR适用于每次增1的计数场景,INCRBY用于指定增量的动态步长;二者均原子执行,避免GET+SET导致的数据丢失。

计数器该用 INCR 还是 INCRBY?
直接用 INCR 就行,它原子性地加 1 并返回新值,适合点击量、访问次数这类每次只增 1 的场景。如果需要动态步长(比如一次加 5 或减 3),才用 INCRBY。别图省事写成先 GET 再 SET —— 那会丢数据,高并发下多个请求读到同一个旧值,各自加 1 后写回去,结果只 +1 而不是 +n。
Spring Data Redis 怎么调用 INCR?
用 RedisTemplate 的 opsForValue().increment() 方法,传入 key 即可。注意两点:一是 key 类型必须是字符串(StringRedisTemplate 更安全);二是首次调用时,Redis 会自动把 key 初始化为 0 再 +1,不用提前 SET。
示例:
String key = "page:views:home"; Long count = stringRedisTemplate.opsForValue().increment(key);
如果 key 已存在且值不是整数,会抛 org.springframework.dao.DataAccessException,错误信息类似 ERR value is not an integer or out of range —— 检查是否误存了 JSON 字符串或空值。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
怎么保证计数器不被误删或过期?
默认 Redis 不设过期时间,但如果你手动加了 EXPIRE 或用 set(key, value, timeout),计数器就可能突然归零。除非业务明确需要“7 天热度统计”这类时效性要求,否则不要设过期。另外,避免在清理缓存脚本里匹配 *count* 通配符删键 —— 很容易误伤。
- 上线前检查所有
DEL/SCAN+DEL脚本,排除对计数器 key 的批量操作 - 关键计数器建议加命名空间前缀,比如
counter:order:success,和业务缓存区分开 - 如果要用过期,改用
INCR+ 独立的定时任务维护 TTL,而不是依赖 key 自带过期
高并发下要不要加锁?
不用。Redis 的 INCR 本身就是单线程原子操作,吞吐量轻松扛住每秒几万次递增。加 Redis 分布式锁反而引入额外延迟和失败风险。唯一要注意的是:别把计数逻辑包在 Spring 的 @Transactional 里 —— 如果事务回滚,Redis 计数不会回退,会导致数据库和计数器不一致。计数器更新应该独立于 DB 事务,作为最终一致的旁路统计。
真正要小心的是“读-改-写”类需求,比如“仅当当前值小于 100 才允许加”。这时得用 Lua 脚本封装判断和递增,否则竞态条件无法避免。

















