задний план
Когда мы работали сообществом, часто были одноклассники, которые ставили столбы для воды. Для такого рода вредоносной очистки наши одноклассники-операторы очень обеспокоены, и этот вид фильтрации не может быть выполнен на шлюзе, например, ip, и может быть обработан только на основе одного пользователя.Наша обычная стратегия: количество сообщений в минуту не может превышать 2, после этого маленькую темную комнату закрыть на 10 минут.
Сценарий внешнего вида
- Противощеточный механизм поста упомянут выше.
- Анти-свайп для рекламного трафика.
- Запрос интерфейса не может быть обработан механизмом прерывателя цепи.
- ......
решение
Для такого рода «черных и злых» запросов мы должны закрыть маленький черный дом. Конечно, некоторые системные архитектуры относительно велики, и они были закрыты на уровне шлюза. Мы сделаем это здесь на уровне бизнеса, потому что мы Бизнес не очень большой, конечно, студенты также могут перенести это на уровень шлюза, чтобы ему не нужно было проникать на нашу бизнес-сторону, по крайней мере, это может уменьшить внутренний сетевой трафик нашего компьютерного зала.
блок-схема
Описание потока
- Интерфейс инициирует запрос, и сервер получает уникальный идентификатор пользователя (идентификатор пользователя, номер телефона...).
- Определите, заблокирован ли пользователь, и верните код ошибки напрямую, если он заблокирован.
- Если он не заблокирован, отметьте запрос, или наложите его (в суперпозиции есть яма, смотрите вниз).
- Вычислите, превышает ли текущий пользователь установленный нами порог в течение определенного периода времени. Если он не превышен, возвращайтесь напрямую.
- В случае превышения он будет заблокирован, а затем возвращен, и решение будет принято при следующем запросе.
конкретный план
В нашем сценарии в качестве примера используется распределенная блокировка и атомарный счетчик Redis.
Наложение во времени, чтобы определить, превышает ли наложенное значение пороговое значение
Эта схема, когда ее разработают многие, будет считать, и это не кажется большой проблемой.Основной процесс такой:
- Предположим, мы используем Redis для атомарного подсчета, каждый раз, когда мы входим, мы выполняем операцию incr и устанавливаем для нашего ключа пороговое время истечения срока действия.
//将我们用户请求量叠加1
$request_nums = Redis::incr('user:1:request:nums',1);
//第一次叠加,设置key的过期时间
if ($request_nums == 1){
Redis::expire('user:1:request:nums',300);
}
if($request_nums > 10){
//加入小黑屋,下次再进来就要锁定判断
}
...
- Каждый запрос будет наложен сначала, а затем в пределах этого допустимого интервала будет подсчитано количество запросов, если количество запросов превышает порог, то закрыть маленькую черную комнату, а если нет, то продолжать ходить.
Вопрос: На первый взгляд, проблем нет. Каждый расчет находится в пределах моего интервала. Это может гарантировать, что количество запросов в интервале не является проблемой, и нам все еще нужен наш атомарный счетчик Redis, но здесь есть проблема. user В обоих временных промежутках проблем нет, но эта точка во временных промежутках не учитывается.
Итак, есть ли способ решить проблему неточного расчета периода времени, вызванного этой проблемой задержки времени?
Ответ определенно да, я собираюсь использовать упорядоченную коллекцию Redis.
Запрос не различает периоды времени и напрямую пишет в упорядоченную коллекцию
Грубый процесс:
- Каждый запрос записывается в упорядоченную коллекцию.Исходным значением коллекции является текущая отметка времени в миллисекундах (для предотвращения повторения секунды).Можно считать, что каждый запрос имеет отметку времени в нем.
- Удалите все данные коллекции за 10 минут назад из коллекции. Затем вычислить число в текущем наборе
- По этому числу мы судим о размере нашего порога, если он превышается, он будет заблокирован, иначе продолжит ходить.
//将我们时间戳写入我们redis的有序集合里面
Redis::zadd('user:1:request:nums',1561456435,'1561456435.122');
//设置key的过期时间为10分钟
Redis::expire('user:1:request:nums',300);
//删除我们10分钟以前的数据
Redis::ZREMRANGEBYSCORE('user:1:request:nums',0,1561456135);
//获取里面剩下请求个数
$request_nums=(int)Redis::zcard(self::TIMELINE_ELEVEL_KEY);
if($request_nums >= 10){
//加入小黑屋,下次再进来就要锁定判断
}
...
Поскольку мы записываем не просто значение, а записываем время запроса, то со временем наша статистика запросов не будет хронологической.
Суммировать
- В начале я постоянно думал о проблеме первого плана.Позже при обсуждении плана я всегда обнаруживал, что время сдвинулось, и значение должно быть изменено, но в первом плане наш объем запроса не будет Изменить , наш период времени превратился в ценность.
- Мы используем упорядоченный набор Redis для создания общего дизайна решения. Конечно, есть лучшие решения. Добро пожаловать, чтобы порекомендовать. Это сильное давление на Redis для чтения и записи, но как временное хранилище данных, этот сценарий относительно встречает.
- Все наши операции Redis рекомендуется атомизировать.Это может использовать официальный сценарий lua для объединения нескольких операторов в один оператор, и скорость выполнения lua также очень высока.
Спасибо всем за чтение! ! !