You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot Redis实现线程安全的最大值n自增后重置功能

解决方案

要实现Redis中key值自增到最大值n后重置,同时保证线程安全,核心是利用Redis的原子操作——因为Redis是单线程执行命令,Lua脚本可以确保整个逻辑的原子性,避免并发场景下的竞态问题。

实现步骤

1. 编写Lua脚本

Lua脚本会在Redis中原子执行,逻辑如下:

  • 对指定key执行自增操作
  • 判断自增后的值是否超过最大值max
  • 若超过则将key重置为1,返回1;否则返回自增后的值
local key = KEYS[1]
local max = tonumber(ARGV[1])
local current = redis.call('INCR', key)
if current > max then
    redis.call('SET', key, 1)
    return 1
end
return current

2. Java代码集成

通过RedisTemplate执行上述Lua脚本,确保操作的原子性:

@Autowired
private RedisTemplate<String, Object> redisTemplate;

// 预定义Lua脚本,避免重复编译
private static final String INCR_RESET_SCRIPT = 
        "local key = KEYS[1]\n" +
        "local max = tonumber(ARGV[1])\n" +
        "local current = redis.call('INCR', key)\n" +
        "if current > max then\n" +
        "    redis.call('SET', key, 1)\n" +
        "    return 1\n" +
        "end\n" +
        "return current";

public long saveAndGetNextValue(long max) {
    DefaultRedisScript<Long> script = new DefaultRedisScript<>();
    script.setScriptText(INCR_RESET_SCRIPT);
    script.setResultType(Long.class);
    
    // 执行脚本:传入key列表和max参数
    return redisTemplate.execute(script, Collections.singletonList("myKey:"), max);
}

3. 注意事项

  • RedisTemplate序列化配置:确保key的序列化器为StringRedisSerializer,避免key出现乱码导致脚本无法识别:
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
        template.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
        template.afterPropertiesSet();
        return template;
    }
    
  • 最大值max的取值:需传入正整数,若key不存在,首次自增会将其设为1,符合重置后的初始值逻辑。

为什么线程安全?

Redis执行Lua脚本时会阻塞其他命令,整个脚本的执行过程是原子的,不会被并发请求打断,因此完全避免了多线程场景下的竞态条件问题。

内容的提问来源于stack exchange,提问作者Bopanna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:37:12