Особенности средних нагрузок
В этой статье я постараюсь описать те проблемы и пути их решения, с которыми я впервые столкнулся при работе с проектами с суточной посещаемостью 300 тысяч человек и более.
Для меня, как начинающего в этой области, было сложно найти некоторую отправную точку. Думаю, я такой не один и информация, изложенная в этой статье, пригодится кому-то еще. Сразу скажу, что когда проект работает на высоких нагрузках, то оптимизация и настройка его производится индивидуально в каждом случае, однако, используемые инструменты одинаковы.
Очевидно, что работа с проектом при таких нагрузках ведется исключительно на выделенных серверах, поэтому далее я буду учитывать, что мы имеем в своем полном распоряжении один или более выделенных сервера.
Все проводимые работы можно условно разделить на несколько фронтов – база данных, сами скрипты и организация группы серверов.
Не хочу превращать статью в кучу общих слов, поэтому опишу пример, который буду в дальнейшем рассматривать.
Допустим, у нас есть социальная сеть вроде news2.ru. Зайдя на главную страницу сайта, мы можем увидеть список рекомендованных новостей и всякие другие полезные списки, которые отображаются на каждой странице сайта. Такие элементы далее будем называть виджетами (не совсем корректно, но условимся что это так).
Запросы к БД
Так вот, при заходе любого посетителя на сайт этот виджет должен брать информацию из базы данных. А теперь представьте, что каждую секунду на сайт заходят по несколько новых человек + роются там постоянные посетители. По сравнению со всеми другими элементами сайта – виджеты создают большую часть нагрузки на базу.
Как бы вы не оптимизировали запросы к базе данных из этих виджетов, даже средняя нагрузка напрочь положит проект. Нашим спасательным кругом в этом случае становится то, что информация в этих виджетах обновляется не так часто и ее можно кэшировать.
Такие “горячие” данные обычно кэшируют в памяти через memcached. Кэшировать их на файлах было бы не разумно, потому что база данных, по сути, тоже файловое хранилище и нагрузка на жесткий диск изменится незначительно.
Итак, как только мы начнем кэшировать данные в памяти, нагрузка на сервер сократится в разы.
Примечание:
Нагрузка на сервер не является абстрактной величиной и может быть количественно измерена. В начале статьи я писал о том, что у нас есть доступ к выделенному серверу. Я работал с выделенными серверами под управлением ОС FreeBSD, поэтому буду рассматривать на ее примере. Чтобы посмотреть насколько загружен Ваш сервер в текущий момент, воспользуйтесь командой “top” – она покажет загрузку каждого из процессоров в виде десятичного числа (Например, 1.05 или 10.2 и т.д.).
Что ж, теперь у нас есть средство для мониторинга загрузки сервера.
Далее, несмотря на то, что мы кэшировали большую часть “лишних” запросов, нам необходимо оптимизировать оставшуюся часть.
Тут нам на помощь приходит второе средство мониторинга загрузки (на этот раз базы данных).
Я работал с СУБД MySQL, поэтому далее буду рассматривать только ее. При заходе в консоль рабочей базы данных пишем запрос: show full processlist; либо show processlist;
Эти запросы выводят список активных запросов к базе данных (которые выполняются в настоящий момент).
Кроме самих запросов в нем присутствует такой параметр как время ее выполнения. Запросы, время выполнения у которых самое большое необходимо либо оптимизировать, либо кэшировать (если они еще не кэшированы).
Другой способ определения запросов, которые нужно оптимизировать – это делать частые снимки активных запросов и смотреть на те, которые часто там появляются.
Частые INSERT`ы.
Последнее, что хочу заметить относительно запросов к базе данных – это ведение статистики. Во всех системах статистики производится частые вставки (INSERT) в одну таблицу или группу таблиц. При больших нагрузках все запросы на запись могут не успевать обрабатываться , поэтому они будут сбрасываться. Чтобы этого не происходило, вместо запросов вида INSERT, используйте запись INSERT DELAYED, тогда запросы будут просто суваться в очередь, которая со временем будет разгребаться сервером.
Сессии
Сессии, как и база данных, по сути, является файловым хранилищем (файлы сессий хранятся на жестком диске сервера), поэтому обращение к ним следует минимизировать. Довольно часто данные, которые хранятся в сессиях, можно перенести в куки пользователей. В этом случае нагрузка с сервера будет снята. Единственное, что необходимо помнить в этом случае – это то, что данные в куках находятся под полным контролем пользователей и некоторые их них могут изменить их. Меры защиты для чувствительных данных должны быть приняты в этом случае.
Организация системы серверов.
Если нагрузки на проект действительно большие, то, как бы данные не кэшировали и не оптимизировали запросы – этого все равно будет недостаточно, и сервер не будет иметь должное время отклика. В таких случаях уже необходимо добавлять сервера и как-то распределять нагрузки между ними.
Прежде чем расширять серверную базу, необходимо определить на какую часть системы приходится большая нагрузка (узкое место системы). Далее рассмотрим два возможных слабых места системы: база данных и веб-сервер.
База данных
Когда одна база данных не справляется с количеством запросов, нужно добавить еще один сервер для нее.
Однако, новые возможности, как правило, рождают и новые обязательства. При добавлении нового сервера базы данных мы не сможем тупо разделить весь трафик между ними средствами системного администрирования. Нам нужно будет определить какие запросы направлять на вторую БД. В нашем случае это может быть вся система статистики и еще какие-нибудь служебные данные. С этим все ясно.
Другой случай может оказаться сложнее, и в другую БД будет писаться информация, которая потом будет использоваться на проекте (на основном сервере). Поэтому данные двух баз данных нужно как-то синхронизировать. Для решения этой задачи во всех современных СУБД существует механизм репликации.
Суть его заключается в том, что на фоне работы СУБД все время действует процесс, который все изменения в нашей базе периодически перебрасывает в другую базу.
Схемы репликации бывают разными, как и способы передачи данных используемые в них (об этом можно почитать подробнее в инете).
При больших нагрузках проблемы бывают не только с базой данных, но и с самим веб-сервером.
Скрипты, как их не оптимизируй создают большую нагрузку на процессор. В этом случае, так же необходимо расширять серверную базу, но на этот раз, на втором сервере будет установлен второй веб-сервер.
Веб-сервера.
Распределение трафика между веб-серверами уже можно настроить средствами системного администрирования, однако, тут возникает ряд других проблем.
Предположим, что у нас есть два веб-сервера, естественно расположенных на разных машинах.
Тогда, на каждом веб-сервере необходимо держать копию всех скриптов и файлов, необходимых для работы проекта. Это раз.
Во-вторых, механизм сессий, как известно, работает с обычными файлами, расположенными где-то на сервере. Следовательно у каждого веб-сервера свои файлы сессии. И если пользователь зашел на главную страницу сайта и залогинился там (логин сохранился в сессиях), а потом перешел по ссылки на другую страницу, то в его сессии может уже не оказаться логина, потому что веб-сервер используется уже другой.
Итак, две проблемы обозначены.
Первая решается по-разному, например, можно синхронизировать файлы и скрипт между серверами командой “rsync” выполняемой по расписанию (раз в минуту допустим). Но это уже вопросы администрирования…
Для решения второй проблемы я знаю только один способ – хранить данные вместо сессий в куках пользователя. Если кто-то подскажет что-то еще буду очень рад.
На этом у меня все. Удачи.
Июнь 23rd, 2009
“Кэшировать их на файлах было бы не разумно, потому что база данных, по сути, тоже файловое хранилище и нагрузка на жесткий диск изменится незначительно.”
Ну это вы зря. Нагрузка на диск – может быть, а вот время отклика в случае файликов, по сравнению с БД, уменьшится значительно. На мой взгляд, кеш на файлах – первая стадия решения. Благо, он может быть реализован на любом хостинге с минимальными затратами времени.
“Для решения второй проблемы я знаю только один способ – хранить данные вместо сессий в куках пользователя. Если кто-то подскажет что-то еще буду очень рад.”
Как вариант, хранить в куках id сессии, а всю иё инфу – в мемкеше (плюс БД на случай протухания кеша).
Июнь 23rd, 2009
“Кэшировать их на файлах было бы не разумно, потому что база данных, по сути, тоже файловое хранилище и нагрузка на жесткий диск изменится незначительно.”
Ну это вы зря. Нагрузка на диск – может быть, а вот время отклика в случае файликов, по сравнению с БД, уменьшится значительно. На мой взгляд, кеш на файлах – первая стадия решения. Благо, он может быть реализован на любом хостинге с минимальными затратами времени.
“Для решения второй проблемы я знаю только один способ – хранить данные вместо сессий в куках пользователя. Если кто-то подскажет что-то еще буду очень рад.”
Как вариант, хранить в куках id сессии, а всю её инфу – в мемкеше (плюс БД на случай протухания кеша).
Июнь 23rd, 2009
>база данных, по сути, тоже файловое хранилище
1. Смотря какая СУБД и какой Storage Engine (см. MySQL MEMORY например)
2. Мемкеш тоже БД
Июнь 23rd, 2009
>Другой способ определения запросов, которые нужно оптимизировать
смотрите log-slow-queries
Июнь 23rd, 2009
>Сессии
Мы как раз для этого используем Memcached
Июнь 23rd, 2009
>Для решения второй проблемы я знаю только один способ – хранить данные вместо сессий в куках пользователя. Если кто-то подскажет что-то еще буду очень рад.
еще раз – memcache
Июнь 24th, 2009
2 Глеб Белогорцев:
“Как вариант, хранить в куках id сессии, а всю иё инфу – в мемкеше (плюс БД на случай протухания кеша).”
Этот вариант будет работать только в случае когда два сервера связаны в локальную сеть (в одной стойке стоят например в дата центре).
Июнь 24th, 2009
>Этот вариант будет работать только в случае когда два сервера связаны в локальную сеть
Почему?
Июнь 24th, 2009
2 adw0rd: Если обращаться в мемкешу через сеть, то это будет тормознуто работать, особенно если учитывать что там объемы данных будут большие при нагрузках.
Июнь 24th, 2009
2 cryptus: так ведь это только данные сессии, их много навряд ли будет. Конечно, надо смотреть в каждом конкретном случае, но скорее всего, сходить на другой сервер за готовыми данными будет быстрее, чем собирать их из БД (которая, кстати, тоже может оказаться на отдельном сервере).
Июнь 30th, 2009
Что такое Cookia?И зачем он нужен?
Июнь 30th, 2009
Июнь 30th, 2009
2Людмила
Июль 15th, 2009
> INSERT DELAYED
Этот режим не поддерживается InnoDB, поэтому в большинстве таблиц им не воспользоваться. Использовать MyISAM и отложенные вставки надо на таблицах, доля вставок записей в которых велика относительно запросов select. Это, например, таблицы хранения “сырых” данных по статистике посещения. В остальных случаях не целесообразно отказываться от преимуществ InnoDB.
Август 18th, 2009
300 человек в день равносильно тому что у вас одновременно не более 10 человек на сайте.
Вот у меня одновременно от 60 до 150 человек, как стало переваливать за 100, тогда пришлось оптимизировать.
Сентябрь 19th, 2009
Для больших проектов лучше использовать DLE.Особенно кеш мне там нравиться
Сентябрь 29th, 2009
“300 тысяч человек” – АХРЕНЕТЬ!!! (завидую)
Толковая статейка. Хотелось бы узнать из Вашего блога больше про XML. Вы очень доходчиво пишете.
Октябрь 21st, 2009
Интересно…. реальная цифра…. с трудом верица мне..
Декабрь 7th, 2009
Спасибо. Продолжение было бы весьма интересно.
Декабрь 11th, 2009
>> Для больших проектов лучше использовать DLE.Особенно кеш >> мне там нравиться
Серьезно? ) Цифры есть или голословно?
Статья неплохая, правда вот теория кругом одна, нет бы что-нибудь из реализации показать )
Декабрь 11th, 2009
Вы еще не упомянули про раздельную обработку статики и динамики. Статику (картинки, джаваскрипт и CSS) можно отдавать легким сервером, наподобие nginxX или lighttpd.
Динамику можно перекидывать на Апач или другой сервер (томкат, например, если используется Java).
Т.е. используется двухзвенная система из веб-серверов. На фронте (на морде) стоит легкий сервер, который обрабатывает статику. А запросы на динамику он передает на бек-енд сервер (Апач, томкат и т.п.).
…
Я бы начинал оптимизировать именно с этого.
Второй вещью, которой бы сделал – это использование кешера, типа memcached.
Декабрь 22nd, 2009
Немного критики )
>> Во всех системах статистики производится частые вставки (INSERT) в одну таблицу или группу таблиц…
Во всех системах статистики ведется т.н. промежуточное кеширование информации. Т.е. висит себе демон в памяти и сбрасывает все в файлик с критической частотой. А по расписанию кидает все в базу (вспоминаем пересчеты статистики li.ru и иже с ними)
>> Другой случай может оказаться сложнее, и в другую БД будет писаться информация, которая потом будет использоваться на проекте (на основном сервере). Поэтому данные двух баз данных нужно как-то синхронизировать.
Схему репликации Master-Master крайне не советую использовать.
По поводу базы. Некритичные данные можно инсертить на мастер-сервер, а забирать из слейв-сервера. Но такая схема работы подразумевает жесткое условие: Идет обновление данных – работаем с мастером. Идет чтение – работаем со слейвом. На проектах, с 1к запросами в секунду (биллинг) только так и получается балансировать на грани сохранения резерва вычислительной мощности двух серверов.
>> Сессии, как и база данных, по сути, является файловым хранилищем (файлы сессий хранятся на жестком диске сервера), поэтому обращение к ним следует минимизировать.
Даже если вы уберете данные из сессии, то идентификатор-то все-равно лежит на ФС. А скорость доступа к файлу, в основном, зависит от скорости поиска. Т.е. изменение размера файла сессии с 5кб на 1кб вы ничего не получите. Только геморрой и будете тратить лишнее процессорное время на операции анализа куков (или, неявно, воспользуетесь стандартным разборщиком). Обратите внимание, что от хранения файлов сессий на ФС вы так и не отказались
>> Скрипты, как их не оптимизируй создают большую нагрузку на процессор.
Число пи высчитываете? При загрузке процессора 0.75 php-cgi (спаунинг) ест не более 0.01. Остальное – СУБД.
Январь 20th, 2010
Хорошая статья. Интересная. Об этом можно целый блог отдельный открыть. А может быть такой уже есть и кто то знает?
Для начинающего (растущего) программиста, менеджера проектов подобную информацию не найти. Она очень ценная. Спасибо.