这是一个旧问题,已经有答案了,但是我从这里得到了一些灵感并进行了实现。我正在使用Node.js的
ioredis。
以下是异步且无竞争条件(我希望如此)的滚动时间窗口限制器:
var Ioredis = require('ioredis');
var redis = new Ioredis();
var redis_limiter_rolling = function(key, maxnum, exp, next) {
redis.multi([
['incr', 'limiter:num:' + key],
['time']
]).exec(function(err, results) {
if (err) {
next(err);
} else {
var listnum = results[0][1];
var tcur = (parseInt(results[1][1][0], 10) * 1000) + Math.floor(parseInt(results[1][1][1], 10) / 1000);
var texpiry = tcur - exp;
var listkey = 'limiter:list:' + key;
redis.multi([
['zadd', listkey, tcur.toString(), listnum],
['zremrangebyscore', listkey, '-inf', texpiry.toString()],
['zcard', listkey]
]).exec(function(err, results) {
if (err) {
next(err);
} else {
var num = parseInt(results[2][1], 10);
if (num <= maxnum) {
next(null, false, num, exp);
} else {
next(null, true, num, exp);
}
}
});
}
});
};
这里是一种锁定式的速率限制器:
var util_limiter_lockout = function(key, maxnum, exp, next) {
var idkey = 'limiter:lock:' + key;
redis.incr(idkey, function(err, result) {
if (err) {
next(err);
} else {
if (result <= maxnum) {
redis.expire(idkey, exp, function(err) {
if (err) {
next(err);
} else {
next(null, false, result);
}
});
} else {
next(null, true, result);
}
}
});
};
这里是函数的要点。如果您发现任何问题,请告诉我。
counter
是有意义的,特别是如果你有很多counter
键。 - keunenow() - time < 60
)分钟的时间间隔... - Kanagavelu Sugumar