分布式限流

分布式限流最关键的是要将限流服务做成原子化,而解决方案可以使用 Redis+Lua 或者 Nginx+Lua 技术实现,通过这两种技术可以实现高并发和高性能。本文使用 Redis+Lua 实现时间窗内某个接口的请求数限流,实现了该功能后可以改造为限流总并发/请求数和限制总资源数。

Redis+Lua实现脚本

1
2
3
4
5
6
7
8
9
10
local key = KEYS[1]
local limit = tonumber(ARGV[1]) #限流大小
local current = tonumber(redis.call('get',key) or "0") #获取不到 默认为0
if current + 1 > limit then #如果超出限流大小
return 0
else #请求数+1,并设置2秒过期
redis.call("INCRBY",key,"1")
redis.call("expire",key,"2")
return 1
end

Java中判断是否需要限流的代码

1
2
3
4
5
6
7
8
9
10
11
public static boolean () throws Exception {
//redis lua 脚本
String luaScript = Files.toString(new File("xxxxLimit.lua")),Charset.defaultCharset());
//将当前时间戳取秒数(极端情况下机器时钟不准时会存在一些小问题)
String key = "ip:" + System.currentTimeMillis()/1000;
//限流大小
String limit = "30";
//执行脚本
return (Long)jedis.eval(luaScript,Lists.newArrayList(key),Lists.newArrayList(limit)) == 1;
}