限流

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

原文地址:https://www.cnblogs.com/wumian1360/p/7791507.html