Mastering Distributed Rate Limiting with Redis, Lua, and Java

This article explains why rate limiting is essential for high‑availability systems, compares single‑node and distributed approaches, and provides a complete Redis + Lua implementation with Java integration, including code samples and architectural diagrams to help developers.

Java High-Performance Architecture
Java High-Performance Architecture
Java High-Performance Architecture
Mastering Distributed Rate Limiting with Redis, Lua, and Java

1. Rate Limiting

In high‑concurrency systems, protection mechanisms such as caching, degradation and rate limiting are used; caching speeds up access, degradation sacrifices non‑essential services under heavy load, and rate limiting throttles requests (reject, queue, wait) to ensure high availability.

2. Distributed Rate Limiting

On a single machine, rate limiting can be placed directly in the service interface, e.g., using Guava RateLimiter.

In a distributed system, multiple instances of a service require a unified rate‑limiting control, typically placed in an API gateway.

The core of distributed rate limiting is an atomic service; common solutions are Redis + Lua and Nginx + Lua.

3. Redis + Lua Implementation

Lua script (executed atomically in Redis):

-- Get the first key (used as rate‑limit key)
local key = KEYS[1]
-- Get the first argument (limit size)
local limit = tonumber(ARGV[1])

-- Get current traffic
local curentLimit = tonumber(redis.call('get', key)) or "0"

-- Check if limit exceeded
if curentLimit + 1 > limit then
    -- Reject
    return 0
else
    -- Increment
    redis.call("INCRBY", key, 1)
    -- Set expiration
    redis.call("EXPIRE", key, 2)
    -- Allow
    return 1
end

Because Redis runs single‑threaded, the Lua script is thread‑safe.

Java example that loads the script and evaluates it:

public boolean limit() throws Exception {
    String luaScript = Files.toString(new File("limit.lua"), Charset.defaultCharset());
    Jedis jedis = new Jedis(ip, port);
    String key = "ip:" + System.currentTimeMillis() / 1000;
    String limit = "3";
    ArrayList<String> scriptKeys = Lists.newArrayList(key);
    ArrayList<String> scriptArgs = Lists.newArrayList(limit);
    return (Long) jedis.eval(luaScript, scriptKeys, scriptArgs) == 1;
}
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Distributed Systemsjavarate limiting
Java High-Performance Architecture
Written by

Java High-Performance Architecture

Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.