限流
API限流
之前做项目,一直有做API限流方面的项目,当时是用Redis的string结构存储,然后过期时间设置为5秒。
主要思路住下:
1.用Incrby设置key,当存在值加1,否则值为1
2.然后将incrby返回的值,跟最大限流速度比较,大于则返回失败,否则继续
这样做,没什么问题,但是这段代码每次都需要自己写incrby,而且这个放入不可以重用。
后期看了开涛的高并发系列
有个使用lua的脚本语句,感觉非常好用
local key=@key --限流KEY(一秒一个)
local limit=tonumber(@limit) --限流大小
local current=tonumber(redis.call('get',key) or "0")
if current+1 > limit then
return 0
else
redis.call("INCRBY",key,"1")
redis.call("expire",key,"200")
return 1
end
使用redis第三方库StackExchange集合
主要代码如下:
/// <summary>
/// 是否到达最大速度
/// </summary>
/// <returns>1:是,0:否</returns>
public static int IsMaxSpeed(int maxSpeed)
{
string luaPath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory.Replace("\\bin\\Debug", ""), "redis\\limit.lua");
string lua = File.ReadAllText(luaPath);
var redis = ConnectionMultiplexer.Connect("127.0.0.1:6379,allowAdmin = true,password=123");
var result = redis.GetDatabase().ScriptEvaluate(LuaScript.Prepare(lua), new { key = "Customer:Limit:Speed" + DateTime.Now.ToString("HHmmss"), limit = maxSpeed });
if (result.IsNull == true)
{
return 0;
}
return int.Parse(result.ToString());
}
优点:
1.脚本语句可以共用
2.不依赖于key,每次可以传入key