Найти тему
2015 подписчиков

👣 Флуд-контроль с помощью redis timeseries и Go


Итак, сразу к сути.
Несколько экземпляров приложения могут стучаться к флуд-контролю, поэтому нужно использовать какую-нибудь БД.

⏩1 идея: использовать SQL. Проблема: много возни с индексами по timestamp, т.к. обновление данных очень частое, следовательно перестройка индексов будет занимать много времени.

⏩2 идея: использовать redis + timeseries. Решил воспользоваться ввиду наличия всех нужных методов: добавление timestamp по ключу (очевидно userID), а также любого числового значения (количество запросов во время timestamp); плюс наличие агрегации, автоматического удаления старых меток и готовой concurrency - если в один timestamp появится несколько нажатий, то они складываются. Осталось лишь написать это на Go.

⏩Есть готовый пакет для работы с redis — github.com/redis/go-redis. В переменные окружения нужно добавить следующие переменные:
FC_REDIS_HOST=localhost
FC_REDIS_PORT=6379
FC_REDIS_PASSWORD=strongpassword
FC_RETENTION=5
FC_MAXCHECKS=4
FC_RETENTION и FC_MAXCHECKS, кстати, можно прописать прямо в коде. FC_RETENTION - количество секунд, за которые можно сделать не более FC_MAXCHECKS запросов.

⏩В коде:
redisClient := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", FC_REDIS_HOST, FC_REDIS_PORT),
Password: FC_REDIS_PASSWORD,
DB: 0,
})

ctx := context.Background()

var rfc FloodControl = &fc.RedisFloodController{
Client: redisClient,
RetentionSeconds: FC_RETENTION,
MaxChecks: FC_MAXCHECKS,
}

v, err := rfc.Check(ctx, 1234567890)

⏩В репе лежит простой docker-compose.yml для запуска redis с timeseries.
RedisFloodController.Check аккуратно возвращает ошибки, не роняя приложение, что важно в проде.

⏩супер быстрый старт
cp .env.sample .env
export $(xargs < .env)
docker compose -f docker-compose.yml up -d
go run .

🖥 GitHub

👣 Флуд-контроль с помощью redis timeseries и Go  Итак, сразу к сути. Несколько экземпляров приложения могут стучаться к флуд-контролю, поэтому нужно использовать какую-нибудь БД.
1 минута