Improvement - Change timeToLive to keepAliveTime #6216

Signed-off-by: lyrric <xx20510@163.com>
pull/6222/head
lyrric 4 months ago
parent 8c3c3d5b5d
commit cc91914ead

@ -245,10 +245,17 @@ public class RedissonRateLimiter extends RedissonExpirable implements RRateLimit
+ "res = nil; "
+ "end;"
+ "local ttl = redis.call('pttl', KEYS[1]); "
+ "if ttl > 0 then "
+ "redis.call('pexpire', valueName, ttl); "
+ "redis.call('pexpire', permitsName, ttl); "
+ "local keepAliveTime = redis.call('hget', KEYS[1], 'keepAliveTime'); "
+ "if (keepAliveTime ~= false and tonumber(keepAliveTime) > 0) then "
+ "redis.call('pexpire', KEYS[1], keepAliveTime); "
+ "redis.call('pexpire', valueName, keepAliveTime); "
+ "redis.call('pexpire', permitsName, keepAliveTime); "
+ "else "
+ "local ttl = redis.call('pttl', KEYS[1]); "
+ "if ttl > 0 then "
+ "redis.call('pexpire', valueName, ttl); "
+ "redis.call('pexpire', permitsName, ttl); "
+ "end; "
+ "end; "
+ "return res;",
Arrays.asList(getRawName(), getValueName(), getClientValueName(), getPermitsName(), getClientPermitsName()),
@ -276,25 +283,26 @@ public class RedissonRateLimiter extends RedissonExpirable implements RRateLimit
}
@Override
public RFuture<Boolean> trySetRateAsync(RateType type, long rate, Duration rateInterval, Duration timeToLive) {
if (timeToLive.toMillis() < rateInterval.toMillis()) {
throw new IllegalArgumentException("The parameter timeToLive should be greater than or equal to rateInterval");
public RFuture<Boolean> trySetRateAsync(RateType type, long rate, Duration rateInterval, Duration keepAliveTime) {
if (keepAliveTime != Duration.ZERO && keepAliveTime.toMillis() < rateInterval.toMillis()) {
throw new IllegalArgumentException("The parameter keepAliveTime should be greater than or equal to rateInterval");
}
return commandExecutor.evalWriteNoRetryAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"redis.call('hsetnx', KEYS[1], 'rate', ARGV[1]);"
+ "redis.call('hsetnx', KEYS[1], 'interval', ARGV[2]);"
+ "redis.call('hsetnx', KEYS[1], 'keepAliveTime', ARGV[4]);"
+ "local res = redis.call('hsetnx', KEYS[1], 'type', ARGV[3]);"
+ "if res == 1 and tonumber(ARGV[4]) > 0 then "
+ "redis.call('pexpire', KEYS[1], ARGV[4]); "
+ "end; "
+ "return res;",
Collections.singletonList(getRawName()),
rate, rateInterval.toMillis(), type.ordinal(), timeToLive.toMillis());
rate, rateInterval.toMillis(), type.ordinal(), keepAliveTime.toMillis());
}
@Override
public boolean trySetRate(RateType mode, long rate, Duration rateInterval, Duration timeToLive) {
return get(trySetRateAsync(mode, rate, rateInterval, timeToLive));
public boolean trySetRate(RateType mode, long rate, Duration rateInterval, Duration keepAliveTime) {
return get(trySetRateAsync(mode, rate, rateInterval, keepAliveTime));
}
@Override
@ -308,12 +316,12 @@ public class RedissonRateLimiter extends RedissonExpirable implements RRateLimit
}
@Override
public void setRate(RateType mode, long rate, Duration rateInterval, Duration timeToLive) {
get(setRateAsync(mode, rate, rateInterval, timeToLive));
public void setRate(RateType mode, long rate, Duration rateInterval, Duration keepAliveTime) {
get(setRateAsync(mode, rate, rateInterval, keepAliveTime));
}
@Override
public RFuture<Void> setRateAsync(RateType type, long rate, Duration rateInterval, Duration timeToLive) {
public RFuture<Void> setRateAsync(RateType type, long rate, Duration rateInterval, Duration keepAliveTime) {
return commandExecutor.evalWriteAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"local valueName = KEYS[2];"
+ "local permitsName = KEYS[4];"
@ -324,12 +332,13 @@ public class RedissonRateLimiter extends RedissonExpirable implements RRateLimit
+ "redis.call('hset', KEYS[1], 'rate', ARGV[1]);"
+ "redis.call('hset', KEYS[1], 'interval', ARGV[2]);"
+ "redis.call('hset', KEYS[1], 'type', ARGV[3]);"
+ "redis.call('hset', KEYS[1], 'keepAliveTime', ARGV[4]);"
+ "if tonumber(ARGV[4]) > 0 then "
+ "redis.call('pexpire', KEYS[1], ARGV[4]); "
+ "end; "
+ "redis.call('del', valueName, permitsName);",
Arrays.asList(getRawName(), getValueName(), getClientValueName(), getPermitsName(), getClientPermitsName()),
rate, rateInterval.toMillis(), type.ordinal(), timeToLive.toMillis());
rate, rateInterval.toMillis(), type.ordinal(), keepAliveTime.toMillis());
}
@Override

@ -57,11 +57,11 @@ public interface RRateLimiter extends RRateLimiterAsync, RExpirable {
* @param mode rate mode
* @param rate rate
* @param rateInterval rate time interval
* @param timeToLive time interval before the object will be deleted
* @param keepAliveTime this is the maximum time that key will wait for new acquire before delete
* @return {@code true} if rate was set and {@code false}
* otherwise
*/
boolean trySetRate(RateType mode, long rate, Duration rateInterval, Duration timeToLive);
boolean trySetRate(RateType mode, long rate, Duration rateInterval, Duration keepAliveTime);
/**
* Use {@link #setRate(RateType, long, Duration)} instead.
@ -91,9 +91,9 @@ public interface RRateLimiter extends RRateLimiterAsync, RExpirable {
* @param mode rate mode
* @param rate rate
* @param rateInterval rate time interval
* @param timeToLive time interval before the object will be deleted
* @param keepAliveTime this is the maximum time that key will wait for new acquire before delete
*/
void setRate(RateType mode, long rate, Duration rateInterval, Duration timeToLive);
void setRate(RateType mode, long rate, Duration rateInterval, Duration keepAliveTime);
/**
* Acquires a permit only if one is available at the

@ -2,10 +2,8 @@ package org.redisson;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.*;
import org.redisson.config.Config;
import java.time.Duration;
import java.util.ArrayList;
@ -18,6 +16,21 @@ import static org.assertj.core.api.Assertions.assertThat;
public class RedissonRateLimiterTest extends RedisDockerTest {
@Test
public void testKeepAliveTime() throws InterruptedException {
RRateLimiter limiter = redisson.getRateLimiter("testKeepAliveTime");
limiter.delete();
limiter.trySetRate(RateType.OVERALL, 1, Duration.ofSeconds(1), Duration.ofSeconds(1));
Thread.sleep(Duration.ofMillis(1100));
assertThat(limiter.isExists()).isFalse();
limiter.trySetRate(RateType.OVERALL, 10, Duration.ofSeconds(2), Duration.ofSeconds(2));
Thread.sleep(Duration.ofSeconds(1));
assertThat(limiter.tryAcquire()).isTrue();
assertThat(limiter.remainTimeToLive()).isGreaterThan(1500);
}
@Test
public void testExpire2() throws InterruptedException {
RRateLimiter rateLimiter = redisson.getRateLimiter("test1");

Loading…
Cancel
Save