Комментарии 18
Спасибо за статью. Интересно и заставляет задуматься, как мы проектируем наши приложения.
Хочу еще добавить, что полезно изучать тулзы и экосистему используемых БД. Например, у PostgreSQL есть Pgbouncer, который будет держать пулл коннектов и т.п.
А также, в крупных компаниях делают иногда учебные аварийные отключения сервисов (скопом), баз данных и т.п., что тоже помогает найти уйму мест, где сервисы ведут себя не по задуманному образу.
В первом скрипте у вас REQUESTS_COUNT = 200000, а в описании 20000
А почему не рассмотрели вариант с Connection Pool? При чем оба: 1) pool внутренний и 2) pool внешний
Не стал сильно углубляться, хотел скорее на базовом сделать акцент, но идея хорошая, возможно в будущем напишу и про это.
Вот это и странно. Самый популярный и правильный для большинства случаев сценарий и не рассмотрели :)
Поддержу. Ведь тот же тест через Singleton может быть нерелевантен, если приложение запускается в несколько инстансов. И тогда пул коннектов, который можно шарить между процессами, становится прямо таки важным аспектом реализации.
Да, верно подмечено, в общем это тема для следующей статьи. Хотя, если я правильно вас понял коннектов будет столько, сколько запущено инстансов, т.е. не такое уж большое число. Хотя да, тест по факту не будет релевантным если шарить пул коннектов, выигрыш в таком случае будет какой?
В целом, ответ на вопрос есть в комментарии @acordell
Если запросов не очень большое количество, то и выигрыш призрачен. Но вот если говорить о большом объёме инстансов, то уйма ресурсов будет уходить на инициализацию соединения. То есть, мы не запускаем, скажем 100 инстансов, в каждом из которых пилим N потоков через Singleton - ситуация тут, когда, скажем, через fastCGI в Python летит 100*N запросов на получение данных.
Спасибо, но как-то все закончилось на самом интересном месте. Есть куча клиентов к базам, которые нифига не потокобезопасные. Более того, их как раз абсолютное большинство, на сколько мне известно. И вот так вот просто взять и разделить конекшен уже не выйдет. При этом в рамках одного потока тоже будет не совсем культурно поднимать соединение на каждый чих. Потому есть потребность в пуле, который рулит соединениями более мудро. Делит их по потокам и прикрывает, когда уже не нужны и проч.
Хорошее замечание, спасибо. Клиент redis-py действительно по дефолту использует пул коннектов и является потокобезопасным из коробки.
Результаты тестирования скорости на 20000 get/set запросов:
- Простой (идёт в тексте первым):
time 3.56 seconds
- Singleton (второй и третий варианты):
time 0.97 seconds
Ну, тут даже пояснять нечего.
Ещё можно не создавать класс метод get_connection, а проверить синглтон в __new__ .
А как же Sentinel? не рассматривали такой вариант?
спасибо за статью!
Правильное подключение к БД: почему, зачем и как