VOOZH about

URL: https://deepwiki.com/hypervel/redis/7-rate-limiting

⇱ Rate Limiting | hypervel/redis | DeepWiki


Loading...
Menu

Rate Limiting

Purpose and Scope

This document provides an overview of the rate limiting subsystem in Hypervel Redis. The rate limiting system provides distributed concurrency control and rate limiting capabilities using Redis as a backend storage mechanism. It enables applications running across multiple servers or processes to coordinate and enforce limits on concurrent operations or request rates.

The rate limiting subsystem consists of two main components:

  • Duration Limiter: Time-window based rate limiting with atomic slot acquisition (see Duration Limiter)
  • Timeout Exceptions: Exception handling for rate limiter timeout conditions (see Timeout Exceptions)

This page covers the overall architecture, conceptual model, and integration patterns. For detailed API documentation and implementation specifics, refer to the child pages.

Sources: src/Limiters/DurationLimiter.php1-182 src/Limiters/LimiterTimeoutException.php1-11


Architecture Overview

The rate limiting subsystem is built on top of the core Redis infrastructure, leveraging the same connection management patterns used throughout the package. The following diagram shows how rate limiting components integrate with the existing Redis client architecture.

System Integration Architecture


Key Integration Points:

ComponentRoleDependencies
DurationLimiterCore rate limiting logicRedisFactory, RedisProxy
RedisFactoryProvides named connectionsConfiguration system
RedisProxyExecutes Redis commandsConnection pool
Lua ScriptsAtomic state operationsRedis server

Sources: src/Limiters/DurationLimiter.php10-38 src/Limiters/DurationLimiter.php116-119


Conceptual Model

The rate limiting system implements a sliding time window approach with slot-based concurrency control. The following diagram illustrates the core concepts and how they interact over time.

Time Window and Slot Management


Core Concepts:

  1. Time Window: A fixed duration (decay seconds) during which a maximum number of operations (maxLocks) can be acquired
  2. Slots: Individual acquisition permits within a window. Each successful acquire() consumes one slot
  3. Sliding Windows: When a window expires, a new window automatically begins with the next acquisition attempt
  4. Atomic Operations: All state checks and modifications execute atomically via Lua scripts to prevent race conditions

State Transitions:

EventState ChangeResult
First acquisition in new windowCreates window with count=1Returns true, remaining=maxLocks-1
Acquisition within window limitsIncrements countReturns true, remaining=maxLocks-count
Acquisition exceeding limitsNo state changeReturns false, remaining=0
Window expirationResets window on next acquisitionNew window created

Sources: src/Limiters/DurationLimiter.php24-37 src/Limiters/DurationLimiter.php64-86


Redis State Structure

The rate limiter stores its state in Redis using a hash data structure. Each limiter instance (identified by name) maintains a single hash key with three fields that track the current time window.

Hash Field Structure


Field Definitions:

FieldTypePurposeExample Value
startInteger (Unix timestamp)Beginning of current time window1704067200
endInteger (Unix timestamp)End of current time window1704067260
countIntegerNumber of acquisitions in current window5

Key Expiration: The hash key expires after decay * 2 seconds to clean up unused limiters. This provides a buffer beyond the window duration to account for clock skew and delayed operations.

Atomic Guarantees: All read-modify-write operations on these fields execute within Lua scripts, ensuring consistency in distributed environments where multiple application instances may attempt concurrent acquisitions.

Sources: src/Limiters/DurationLimiter.php130-152 src/Limiters/DurationLimiter.php163-180


Operation Modes

The DurationLimiter class provides three distinct operation modes for different use cases. Each mode interacts with the Redis state differently to support various rate limiting patterns.

Operation Mode Overview


Method Comparison:

MethodBlockingModifies StateThrows ExceptionTypical Use Case
acquire()NoYes (on success)NoOptimistic acquisition, quick checks
block()YesYes (on success)Yes (on timeout)Critical operations requiring guaranteed slot
tooManyAttempts()NoNoNoPre-flight checks, monitoring, metrics

Public Properties Updated:

After calling acquire() or tooManyAttempts(), the following public properties are updated:

  • $decaysAt: Timestamp when the current window expires
  • $remaining: Number of available slots in the current window

These properties enable applications to provide feedback to users about rate limit status without making additional Redis calls.

For detailed API documentation and usage examples, see Duration Limiter.

Sources: src/Limiters/DurationLimiter.php14-20 src/Limiters/DurationLimiter.php40-106


Lua Script Execution

The rate limiter implements its core logic using Lua scripts executed on the Redis server. This design ensures atomicity and reduces network round-trips by performing all read-modify-write operations in a single server-side execution.

Script Execution Architecture


Script Parameters:

ParameterTypePurpose
KEYS[1]StringLimiter name (hash key)
ARGV[1]FloatCurrent time in microseconds (for precise comparisons)
ARGV[2]IntegerCurrent time in seconds (for window boundaries)
ARGV[3]IntegerDecay duration (window length)
ARGV[4]IntegerMax locks (slot limit)

Atomic Guarantees:

The Lua scripts provide three critical atomic operations:

  1. Check-and-Create: If no window exists, create one atomically
  2. Check-and-Increment: If within window limits, increment count atomically
  3. Check-and-Reset: If window expired, reset to new window atomically

This atomicity prevents race conditions that could occur if these operations were executed as separate Redis commands in distributed environments.

Sources: src/Limiters/DurationLimiter.php67-79 src/Limiters/DurationLimiter.php122-152 src/Limiters/DurationLimiter.php154-180


Use Cases

The rate limiting subsystem supports various distributed concurrency control and rate limiting patterns commonly needed in modern applications.

Common Use Cases


Use Case Patterns:

Use CaseConfiguration ExamplePattern
API Rate LimitingmaxLocks: 100, decay: 60Prevent abuse, 100 requests per minute per client
Job ConcurrencymaxLocks: 10, decay: 300Limit parallel job execution, 10 concurrent workers
Resource ThrottlingmaxLocks: 50, decay: 60Control expensive operations, 50 emails per minute
Distributed SingletonmaxLocks: 1, decay: 300Ensure single execution, 1 task per 5 minutes

Implementation Example:


For complete usage examples and API reference, see Duration Limiter.

Sources: src/Limiters/DurationLimiter.php24-37


Error Handling

The rate limiting subsystem uses exceptions to signal timeout conditions when blocking operations exceed configured wait times.

Exception Hierarchy


When Exceptions Are Thrown:

The LimiterTimeoutException is thrown exclusively by the block() method when:

  1. The limiter cannot acquire a slot within the specified timeout period
  2. The retry loop exceeds the configured wait duration
  3. All retry attempts (with sleep intervals) have been exhausted

Exception Handling Strategy:


For detailed exception documentation, see Timeout Exceptions.

Sources: src/Limiters/LimiterTimeoutException.php1-11 src/Limiters/DurationLimiter.php40-62