【Spring】Spring AOP 结合 Redis + Lua 脚本实现分布式限流
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.time.Duration;
// 使用Spring AOP结合Redis和Lua脚本实现分布式限流
public class DistributedRateLimiter {
private final StringRedisTemplate redisTemplate;
private final DefaultRedisScript<Number> limitScript;
public DistributedRateLimiter(StringRedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
// Lua脚本用于原子操作,限制指定时间窗口内的访问次数
String script = "local key = KEYS[1] " +
"local limit = tonumber(ARGV[1]) " +
"local current = redis.call('get', key) " +
"if current and tonumber(current) > limit then return 0 end " +
"if current then " +
" redis.call('incr', key) " +
" if tonumber(redis.call('get', key)) > limit then " +
" redis.call('expire', key, 1) " +
" end " +
"else " +
" redis.call('set', key, '1', 'EX', 1) " +
"end " +
"return 1";
limitScript = new DefaultRedisScript<>();
limitScript.setScriptText(script);
limitScript.setResultType(Number.class);
}
public boolean isAllowed(String key, int limit) {
Number allowed = redisTemplate.execute(limitScript, keys(key), limit);
return allowed.intValue() == 1;
}
private static List<String> keys(String key) {
return Collections.singletonList(key);
}
}
这个简单的例子展示了如何使用Spring AOP和Redis来实现一个分布式限流器。DistributedRateLimiter
类中定义了一个Lua脚本,该脚本用于原子操作,检查键值的计数是否超过限制,并相应地增加计数或设置键的过期时间。isAllowed
方法用于检查是否允许进行某项操作,如果允许,则返回true
,否则返回false
。
评论已关闭