Skip to content

Support sharding in RedisRateLimiter #3780

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Fangzhou1217
Copy link

Problem Statement:​​
The current implementation of RedisRateLimiter uses a single Redis key for rate limiting counters. This leads to a hot key problem in Redis clusters, where massive requests concentrate on a single Redis shard. The resulting excessive load on individual shards cannot be alleviated through horizontal cluster scaling, creating a performance bottleneck.

​​Proposed Solution:​​
This PR introduces a shards configuration parameter to address the hot key issue. Key enhancements include:

  • Sharded Key Generation:​​ Splits the rate limiting counter into multiple Redis keys using configurable shards
  • ​​Load Balancing:​​ Implements round-robin distribution to evenly balance requests across shards
  • ​​Cluster Scalability:​​ Enables true horizontal scaling of Redis clusters by eliminating single-shard pressure

Signed-off-by: liufangzhou.aaa <[email protected]>
int getShardedReplenishRate(Config config) {
int replenishRate = config.getReplenishRate();
if (config.getShards() > 0) {
replenishRate = replenishRate / config.getShards();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if replenishRate is could not be divisible by shards, the actual rate will less than replenishRate, reminder value should be considered.

@jizhuozhi
Copy link
Contributor

Very useful feature.

The purpose of rate limiting is to protect downstream services from overload. However, in such as e-commerce platforms promotion scenarios almost all requests are concentrated on a hot resource. Since the same resources use the same rate limiting key, they will continuously request the same redis shard, causing redis overload. In order not to affect business functions when redis is overloaded, we will let it go of the request, resulting in failure to achieve the expected rate limiting effect. And because the same rate limiting key always requests the same redis shard, we cannot improve system stability through distributed computing under the original implementation.

I have carefully read the implementation of the code. By adding suffixes to the rate limiting key to obtain different hashtags, the requests can be dispersed to different redis shards to avoid single instance overload. In addition to avoiding single machine overload, since Lua scripts can be executed on different redis instances at the same time, this will greatly improve the parallelism of rate limiting.

/**
* A Round-Robin like index to select a virtual shard.
*/
private final AtomicInteger shardIndex = new AtomicInteger(0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why using Round-Robin?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants