Implementing Rate Limiting and Counters with Redis

Redis provides efficient counting capabilities suitable for rate limiting and access tracking. Common use cases enclude blog view counters and SMS verification code frequency limits.

Basic counters face challenges like preventing refresh-triggered increments. The solution involves tracking user access within specific time windows and storing data in memory before database synchronization.

Redis Configuration

Initialize RedisTemplate with proper serialization:

@Configuration
public class RedisConfiguration {
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(RedisSerializer.string());
        return template;
    }
}

Rate Limiting Implementation

@RestController
public class AccessController {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @RequestMapping("/access")
    public ResponseEntity<String> checkAccess() {
        boolean allowed = checkRateLimit("user_access", 1, 5);
        if (allowed) {
            return ResponseEntity.ok("Access granted");
        } else {
            return ResponseEntity.status(429).body("Rate limit exceeded");
        }
    }
    
    private boolean checkRateLimit(String identifier, int duration, int maxAttempts) {
        String redisKey = "rate_limit:" + identifier;
        
        if (redisTemplate.hasKey(redisKey)) {
            Integer currentCount = Integer.valueOf(
                (String) redisTemplate.opsForValue().get(redisKey)
            );
            
            if (currentCount >= maxAttempts) {
                return false;
            }
            
            redisTemplate.opsForValue().increment(redisKey);
            return true;
        } else {
            redisTemplate.opsForValue().set(redisKey, "1", 
                duration, TimeUnit.MINUTES);
            return true;
        }
    }
}

This implementation tracks access attempts using Redis keys with expiration. When the key exists, the counter increments; if the limits reached, access is denied. New keys are created with expiration times.

Common RedisTemplate Operations

Method Description
expire(K key, long timeout, TimeUnit unit) Set key expiration time
expireAt(K key, Date date) Set key expiration date
getExpire(K key) Get remaining TTL in seconds
hasKey(K key) Check if key exists
delete(K key) Remove specified key
delete(Collection<K> keys) Remove multiple keys
keys(K pattern) Find keys matching pattern
opsForValue().increment(K key) Atomic counter increment

Data Persistence Strategy

For production systems, implement asynchronous data synchronization:

  1. Store counters in Redis for fast access
  2. Use background jobs to persist data to databases
  3. Maintain data consistency through periodic synchronization
  4. Handle edge cases like system failures and network partitions

Tags: Redis Rate Limiting java Spring Boot Counter

Posted on Sun, 10 May 2026 17:33:56 +0000 by helpmeplease1234