Как оптимизировать сервер с большим количеством запросом?
Всем добрый день. Я хочу написать свое приложение, по типу секундомера, с сохранением этих данных в бд. И тут встает вопрос, как оптимизировать относительно большое количество запросов исходящих даже от одного пользователя?
То есть, условно, в минуту замер времени может уходить на сервер от 10 раз + к замеру можно давать штрафы - т.е. мутации. Каждый замер времени это новая строка в таблице или новый документ. Как мне не положить сервер с базой, если, условная 1000 человек может генерировать от 10 000 запросов в минуту.
Деление на микросервисы это то что я планирую внедрить, но больше идей именно правильной оптимизации нет. Может для этого стоит выбрать NoSQL базу вместо реляционной или наоборот? Стоит ли для этих целей разворачивать websocket соединение. Может нужно подключать брокер, по типу кафки? Или есть еще какие то верные решения этой задачи. Подскажите пожалуйста начинающему.
Как понял схема данных следующая:
- Есть замер времени - отедльный объект со своим ID
- У каждого замера времени есть список штампов - конкретного времени
- Эти штампы создают пользователи - отправляют запросы
Для данного кейса мне видится такое решение:
- Используем Redis в качестве БД
- Для ID замеров используем snowflake
- Тип данных Redis для замеров - list (список)
- В каждом списке храним эти штампы - строка или unix timestamp (неважно)
Таким образом, на каждый запрос просто добавляем новый элемент в этот список.
Redis хорошо выдерживает высокую нагрузку + его можно масштабировать.
Благодаря snowflake можно горизонтально мастшабировать свои сервисы.
Также, ты указал websocket - здесь как хочешь. Но в .NET есть реализация Redis которая использует мультиплексирование - здесь он будет уместен.
А какую роль выполняет этот snowflake?
Почему просто GUID не использовать? На разных сервисах он точно не совпадёт (т.к. генерируется на основе hwid). А на одном если даже и совпадёт(?), то делать повтор.
Ну или составной ключ (машина+автоинкремент)
Интересная задача, и если прям про высокую нагрузку говорить, то действительно лучше использовать in-memory базу типа Redis как предлагали выше. Для безопасности можно ее периодически копировать в обычную базу на диске.
2йвариант, если хочется меньше заморачиваться - выбрать облачную бд, которую просто масштабируешь под свои нагрузки и не пытаешься вникнуть, как это сделано. Потипу DTU-based бд в Azure.
Ну а само веб приложение - горизонтальное масштабирование, т.е. много экзепляров приложения + балансер нагрузки, которые лезут все в одну и туже базу.
Мое приложение решает важную для меня проблему, в сравнении с его аналогами. Это именно сохранение в базу всех результатов и синхронизация между платформами, чего не дают сделать широко используемые секундомеры, поэтому формат сборки данных раз в сутки меня не устроит, тем более что это веб приложение, которое не всегда открыто)
А по поводу сбора до завершения. Не имею понятия как вызвать функцию на клиенте, по нажатию кнопки закрытия браузера/вкладки. Думал об этом, но инфы не нашел.
historydev, в том и проблема, что таймер делает запрос после каждой остановки. Я могу конкретизировать функцию приложения. Это секундомер для сборки кубика рубика. Лично я в час делаю около семидесяти сборок стандартной трешки - 70 запросов в час от одного юзера на запись в бд. И я не говорю о людях, что могут быть быстрее или брать более легкие дисциплины. Если брать маштабы в большое количество пользователей, то будет большое количество запросов. Я бы не сказал что этот проект пойдет дальше личного пользования, но как начинающий, которого интересует разработка бекэнда, я хотел бы знать как создать приложение выдерживающее многопользовательскую нагрузку. Кроме как разделения монолита на микросервисы и их репликации на разные сервера, я толком ничего не узнал, а хотелось бы.
historydev, даже не когда, а в каком месте space__0 заниматься оптимизацией без замеров, попусту тратить время, найди сначала узкое место на основании замеров
10000 запросов в минуту - это 167 запросов в секунду. Округлим до 200. Т.е. на один запрос дается 5мс.
Простейший sqlite, с файлом на ssd, делает begin;insert;commit; в таблицу без ключей за 0мс.
Если предположить, что СУБД чуть посерьезней чем sqlite, а web сервер многопоточный, то 10000 запросов в минуту он должен проглотить не заметив.
А в общем случае, если предполагается усиленная запись в БД, то таблицу лучше делать без ключей.
10000 в минуту - это не так много, когда доживете до такого, просто запускайте второй сервер на другом поддомене, или перед серверами ставите перенаправлялку, которая новых клиентов гонит на второй сервер
А если использовать long polling? Ну, чтобы каждый раз не отрабатывать новый запрос, вместо этого не отвечать сразу, а дописывать в один запрос новые данные. Получится всего 1 запрос в {время_таймаута_сервера} секунд.