user_of_toster
@user_of_toster

Как реализовать rate-limiting на redis?

Допустим, хочу сделать лимит 100 запросов в день по ip. Есть два варианта реализовать rate-limiting. После каждого запроса:
1) easy-way: храню ключ по IP, делаю incr(), setExpire(currentTime + 1 day);
Плюсы: легко реализовать, не страдаем по перфомансу
Минусы: окно в 1 день размазывается на несколько дней
2) hard-way: храню все посещения, для каждого в отдельности делаю setExpire, считаю количества посещений с помощью key *. В итоге получается точное окно (1 день).
Плюсы: тяжело реализовать, страдаем по перфомансу (?)
Минусы: точное окно в 1 день, юзер сможет сделать 101 запрос, после истечения 1 запроса.

Вопрос - 1) как реализовать второй вариант в редисе? В голове есть вариант генерировать ключ вида IP:RANDOM_UUID и делать set expire в 1 сутки. Потом искать key по маске IP
2) Насколько второй вариант популярен? Можно ли поставить первый и не париться?
  • Вопрос задан
  • 109 просмотров
Решения вопроса 2
Можно хранить список из времён запросов, ключ IP.
"192.168.15.20": [11, 22, 33, 44],
"192.168.15.22": [10, 24, 35, 42, 46],

Смотреть его длину (< 100 ?), сравнивать текущее время с последним в списке.
Вставлять время разрешенного запроса в начало.

Приходит новый запрос. Дальше псевдокод:
const ip = request.ip;
const ts = Date.now();
const len = Redis.LLEN(ip);

if (len < 100) { // можно 
  Redis.LPUSH(ip, ts);
  return true; // можно выполнять запрос
}

const last_ts = Redis.LRANGE(ip, -1, -1);

if ((ts - last_ts) < 864e5) { // меньше суток
  return false; 
} else {
  Redis.LPUSH(ip, ts);
  Redis.LTRIM(ip, 0, 99);
  return true;
}

И наверное всё это стоит обернуть в MULTI .. EXEC, чтобы параллельные запросы с одного IP на внесли беспорядок.
Ответ написан
@javedimka
Хочу сока
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы