Java利用Redis實現非同步邏輯多使用者併發控制

Jackie_JK發表於2024-12-07
@Service
public class ReportConcurrentService {

  @Autowired
  private RedisTemplate redisTemplate;

  @Autowired
  private RedisConfig redisConfig;

  @Value("${report.user-concurrent:1}")
  private int userConcurrent;

  @Value("${report.common-concurrent:10}")
  private int commonConcurrent;

  private String getUserKey(long userId, String beanName) {
    return redisConfig.getUkPrfex(String.join(":", CoreConstants.REPORT_CONCURRENT_USER_COUNTER, String.valueOf(userId), beanName));
  }

  private String getCommonKey() {
    return redisConfig.getUkPrfex(String.join(":", CoreConstants.REPORT_CONCURRENT_COMMON_COUNTER));
  }

  public void acquire(long userId, String beanName) {
    String commonKey = getCommonKey();
    Long increment = redisTemplate.opsForValue().increment(commonKey);
    redisTemplate.expire(commonKey, 1, TimeUnit.HOURS);
    if (increment != null && increment > commonConcurrent) {
      redisTemplate.opsForValue().decrement(commonKey);
      ReportConcurrentErrorEnum.EXCEEDING_CONCURRENT_LIMIT.fail();
    }
    String userKey = getUserKey(userId, beanName);
    increment = redisTemplate.opsForValue().increment(userKey);
    redisTemplate.expire(userKey, 1, TimeUnit.HOURS);
    if (increment != null && increment > userConcurrent) {
      redisTemplate.opsForValue().decrement(commonKey);
      redisTemplate.opsForValue().decrement(userKey);
      ReportConcurrentErrorEnum.HAS_TASK_IN_EXPORTING.fail();
    }
  }

  public void release(long userId, String beanName) {
    String key = getCommonKey();
    redisTemplate.opsForValue().decrement(key);
    key = getUserKey(userId, beanName);
    redisTemplate.opsForValue().decrement(key);
  }

}

相關文章