Прежде чем ответить на этот вопрос, я никогда не разрабатывал ничего настолько популярного, чтобы достигать высоких нагрузок на сервер. Относитесь ко мне как к инопланетянину, который только что приземлился на планете, хотя он знает PHP и несколько методов оптимизации.
Я разрабатываю инструмент на PHP, который может привлечь довольно много пользователей, если он работает правильно. Однако, хотя я полностью способен разрабатывать программу, я почти ничего не понимаю, когда дело доходит до создания чего-то, что может иметь дело с огромным трафиком. Итак, вот несколько вопросов (не стесняйтесь также превратить этот вопрос в ветку ресурсов).
Базы данных
На данный момент я планирую использовать функции MySQLi в PHP5. Однако как мне настроить базы данных по отношению к пользователям и контенту? Действительно ли мне нужно несколько баз данных? На данный момент все перемешано в одну базу данных - хотя я рассматривал возможность распространения пользовательских данных в одну, фактического контента в другую и, наконец, основного контента сайта (мастеров шаблонов и т. Д.) В другую. Моя причина в том, что отправка запросов в разные базы данных облегчит их загрузку, поскольку одна база данных = 3 источника загрузки. Кроме того, будет ли это все еще эффективно, если они все были на одном сервере?
Кэширование
У меня есть система шаблонов, которая используется для создания страниц и замены переменных. Основные шаблоны хранятся в базе данных, и при каждом вызове шаблона вызывается его кэшированная копия (HTML-документ). На данный момент у меня есть два типа переменных в этих шаблонах - статическая переменная и динамическая переменная. Статические переменные - это, как правило, названия страниц, названия сайтов, которые меняются не часто; динамические переменные - это то, что меняется при каждой загрузке страницы.
Мой вопрос по этому вопросу:
Скажем, у меня есть комментарии к различным статьям. Что является лучшим решением: сохраняйте простой шаблон комментариев и визуализируйте комментарии (из вызова БД) при каждой загрузке страницы или сохраняйте кэшированную копию страницы комментариев в виде html-страницы - каждый раз, когда комментарий добавляется / редактируется / удаляется страница перечитана.
в заключение
У кого-нибудь есть какие-либо советы / указатели для запуска сайта с высокой нагрузкой на PHP. Я почти уверен, что это работоспособный язык - Facebook и Yahoo! дать ему большой приоритет - но есть ли опыт, который я должен остерегаться?
источник
Ответы:
Нет двух одинаковых сайтов. Вам действительно нужно получить такой инструмент, как jmeter и benchmark, чтобы увидеть, где будут ваши проблемные точки. Вы можете тратить много времени на догадки и улучшения, но вы не увидите реальных результатов, пока не измерите и не сравните свои изменения.
Например, в течение многих лет кеш запросов MySQL был решением всех наших проблем с производительностью. Если ваш сайт работал медленно, эксперты MySQL предложили включить кеш запросов. Оказывается, если у вас высокая нагрузка на запись, кеш на самом деле наносит вред. Если вы включите его без тестирования, вы никогда не узнаете.
И не забывайте, что вы никогда не закончили масштабирование. Сайт, который обрабатывает 10req / s, потребует изменений для поддержки 1000req / s. И если вам хватит удачи, чтобы поддерживать 10 000 req / s, ваша архитектура, вероятно, также будет выглядеть совершенно иначе.
Базы данных
Кэширование
источник
Я ведущий разработчик сайта с более чем 15 миллионами пользователей. У нас было очень мало проблем с масштабированием, потому что мы планировали это РАНЬШЕ и масштабировали вдумчиво. Вот некоторые из стратегий, которые я могу предложить из своего опыта.
СХЕМА Во-первых, денормализуйте свои схемы. Это означает, что вместо того, чтобы иметь несколько реляционных таблиц, вы должны вместо этого выбрать одну большую таблицу. В общем, объединения - это пустая трата ценных ресурсов БД, потому что многократная подготовка и сопоставление записывают дисковые операции ввода-вывода. Избегайте их, когда можете.
Компромисс здесь заключается в том, что вы будете хранить / извлекать избыточные данные, но это приемлемо, потому что пропускная способность данных и внутриклеточная область очень дешевы (большие диски), тогда как множественная подготовка ввода-вывода на несколько порядков дороже (больше серверов) ,
УКАЗАНИЕ Убедитесь, что в ваших запросах используется хотя бы один индекс. Однако будьте осторожны, эти индексы будут стоить вам, если вы будете часто писать или обновлять. Есть несколько экспериментальных приемов, чтобы избежать этого.
Вы можете попробовать добавить дополнительные столбцы, которые не индексируются, которые идут параллельно индексированным столбцам. Затем вы можете иметь автономный процесс, который записывает неиндексированные столбцы по индексированным столбцам в пакетном режиме. Таким образом, вы можете лучше контролировать, когда mySQL потребуется пересчитать индекс.
Избегайте вычисляемых запросов, как чума. Если вам нужно вычислить запрос, попробуйте сделать это один раз во время записи.
КЕШИНГ Я очень рекомендую Memcached. Это было доказано крупнейшими игроками в стеке PHP (Facebook) и является очень гибким. Для этого есть два метода: один - кэширование на уровне вашей БД, другой - кэширование на уровне вашей бизнес-логики.
Параметр уровня БД потребует кэширования результатов запросов, извлеченных из БД. Вы можете хешировать ваш SQL-запрос с помощью md5 () и использовать его в качестве ключа поиска перед переходом в базу данных. Плюс в том, что это довольно легко реализовать. Недостатком (в зависимости от реализации) является то, что вы теряете гибкость, потому что вы относитесь ко всему кэшированию одинаково в отношении срока действия кэша.
В магазине, в котором я работаю, мы используем кэширование на бизнес-уровне, что означает, что каждый конкретный класс в нашей системе контролирует свою собственную схему кэширования и время ожидания кэширования. Это хорошо сработало для нас, но учтите, что элементы, извлекаемые из БД, могут не совпадать с элементами из кеша, поэтому вам придется обновлять кеш и БД вместе.
ОХРАНА ДАННЫХ Репликация только уводит вас. Рано, чем вы ожидаете, ваши записи станут узким местом. Чтобы компенсировать это, убедитесь, что поддерживаете передачу данных как можно раньше. Вы, вероятно, захотите застрелиться позже, если вы этого не сделаете.
Это довольно просто реализовать. По сути, вы хотите отделить ключевой орган от хранилища данных. Используйте глобальную БД для хранения сопоставления между первичными ключами и идентификаторами кластера. Вы запрашиваете это отображение, чтобы получить кластер, а затем запрашиваете кластер, чтобы получить данные. Вы можете чертовски кэшировать эту операцию поиска, что сделает ее незначительной операцией.
Недостатком этого является то, что может быть трудно собрать воедино данные из нескольких сегментов. Но вы также можете обойти это.
ОФФЛАЙН-ОБРАБОТКА Не заставляйте пользователя ждать вашего бэкэнда, если ему это не нужно. Создайте очередь заданий и переместите любую обработку, которую вы можете в автономном режиме, делая это отдельно от запроса пользователя.
источник
Я работал над несколькими сайтами, которые получают миллионы обращений в месяц с помощью PHP и MySQL. Вот некоторые основы:
Я бы порекомендовал прочитать « Создание масштабируемых сайтов» , он был написан одним из инженеров Flickr и является отличным справочником.
Посмотрите мой пост в блоге о масштабируемости, там много ссылок на презентации о масштабировании с использованием нескольких языков и платформ: http://www.ryandoherty.net/2008/07/13/unicorns-and-scalability/
источник
Re: PDO / MySQLi / MySQLND
@ Гэри
Вы не можете просто сказать «не используйте MySQLi», поскольку у них разные цели. PDO почти как уровень абстракции (хотя на самом деле это не так) и предназначен для упрощения использования нескольких продуктов баз данных, тогда как MySQLi специфичен для соединений MySQL. Нельзя сказать, что PDO - это современный уровень доступа в контексте его сравнения с MySQLi, потому что ваше утверждение подразумевает, что прогрессия была mysql -> mysqli -> PDO, а это не так.
Выбор между MySQLi и PDO прост - если вам нужно поддерживать несколько продуктов баз данных, вы используете PDO. Если вы просто используете MySQL, вы можете выбрать между PDO и MySQLi.
Так почему же вы выбрали MySQLi вместо PDO? Увидеть ниже...
@ross
Вы правы в отношении MySQLnd, который является новейшей библиотекой уровня ядра языка MySQL, однако он не заменяет MySQLi. MySQLi (как и в PDO) остается тем же способом, которым вы будете взаимодействовать с MySQL через ваш PHP-код. Оба они используют libmysql в качестве клиента C за кодом PHP. Проблема в том, что libmysql находится за пределами основного движка PHP, и именно в этом и заключается mysqlnd, то есть это Native Driver, который использует внутренние ядра PHP для максимизации эффективности, особенно в том, что касается использования памяти.
MySQLnd разрабатывается самими MySQL и недавно попал в ветку PHP 5.3, которая находится на тестировании RC и готова к выпуску в конце этого года. После этого вы сможете использовать MySQL и MySQLi ... но не PDO. Это даст MySQLi повышение производительности во многих областях (не во всех) и сделает его лучшим выбором для взаимодействия с MySQL, если вам не нужны такие абстракции, как возможности PDO.
Тем не менее, MySQLnd теперь доступен в PHP 5.3 для PDO, и поэтому вы можете получить преимущества от повышения производительности от ND до PDO, однако PDO по-прежнему является базовым уровнем базы данных и поэтому вряд ли сможет извлечь из этого столько же пользы. улучшения в ND, как MySQLi может .
Некоторые полезные тесты можно найти здесь, хотя они сделаны с 2006 года. Вам также нужно знать о таких вещах, как этот параметр .
При выборе между MySQLi и PDO необходимо учитывать множество факторов. В действительности это не будет иметь значения, пока вы не доберетесь до чрезмерно высоких номеров запросов, и в этом случае имеет больше смысла использовать расширение, специально разработанное для MySQL, а не расширение, которое абстрагирует вещи и обеспечивает драйвер MySQL. ,
Это не простой вопрос, который лучше, потому что каждый имеет свои преимущества и недостатки. Вам нужно прочитать ссылки, которые я предоставил, и придумать свое собственное решение, затем проверить его и выяснить. Я использовал PDO в прошлых проектах, и это хорошее расширение, но я выбрал бы чистую производительность MySQLi с скомпилированной новой опцией MySQLND (когда выйдет PHP 5.3).
источник
Общее
Код
Базы данных
Кэширование
Разное
источник
APC - абсолютная необходимость. Мало того, что это делает большую систему кэширования, но выгода от автоматически кэшированных PHP-файлов - это находка. Что касается идеи с несколькими базами данных, я не думаю, что вы бы много выиграли от наличия разных баз данных на одном сервере. Это может дать вам некоторое увеличение скорости во время запроса, но я сомневаюсь, что усилия, которые потребуются для развертывания и поддержки кода для всех трех, при условии, что они синхронизированы, стоили бы того.
Я также настоятельно рекомендую запустить Xdebug, чтобы найти узкие места в вашей программе. Это сделало оптимизацию бризом для меня.
источник
Во-первых, как я думаю, Кнут сказал: «Преждевременная оптимизация - корень всего зла». Если вам не нужно решать эти проблемы прямо сейчас, тогда не сосредотачивайтесь на том, чтобы вначале работать правильно. При этом, если оптимизация не может ждать.
Попробуйте профилировать запросы к базе данных, выяснить, что медленно и что происходит, и придумать стратегию оптимизации из этого.
Я бы исследовал Memcached, так как это то, что многие сайты с высокой нагрузкой используют для эффективного кэширования контента всех типов, и интерфейс объекта PHP к нему довольно приятен.
Разделение баз данных между серверами и использование некоторой техники балансировки нагрузки (например, генерация случайного числа между 1 и # избыточными базами данных с необходимыми данными - и использование этого числа для определения, к какому серверу баз данных подключаться) также может быть отличным способом увеличения эффективность.
Все это довольно хорошо сработало в прошлом для некоторых сайтов с высокой нагрузкой. Надеюсь, это поможет вам начать :-)
источник
Профилирование вашего приложения с помощью чего-то вроде Xdebug (например, рекомендованного tj9991) определенно будет обязательным. Не имеет большого смысла просто вслепую оптимизировать вещи. Xdebug поможет вам найти реальные узкие места в вашем коде, чтобы вы могли разумно потратить время на оптимизацию и исправить куски кода, которые на самом деле вызывают замедления.
Если вы используете Apache, другая утилита, которая может помочь в тестировании, это Siege . Это поможет вам предвидеть, как ваш сервер и приложение отреагируют на высокие нагрузки, по-настоящему справившись с этой задачей.
Любой вид кэш-кода для PHP (например, APC или один из многих других) также очень поможет.
источник
Я запускаю веб-сайт с 7-8 миллионами просмотров страниц в месяц. Не очень много, но достаточно, чтобы наш сервер чувствовал нагрузку. Решение, которое мы выбрали, было простым: Memcache на уровне базы данных. Это решение хорошо работает, если загрузка базы данных является вашей основной проблемой.
Мы начали использовать Memcache для кэширования целых объектов и результатов базы данных, которые наиболее часто использовались. Это сработало, но оно также привело к ошибкам (мы могли бы избежать некоторых из них, если бы мы были более осторожны).
Таким образом, мы изменили наш подход. Мы создали оболочку базы данных (с теми же методами, что и в нашей старой базе данных, поэтому ее было легко переключать), а затем мы создали ее подклассы, чтобы обеспечить доступ к базе данных memcached.
Теперь все, что вам нужно сделать, это решить, может ли запрос использовать кэшированные (и, возможно, устаревшие) результаты или нет. Большинство запросов, выполняемых пользователями, теперь выбираются непосредственно из Memcache. Исключением являются обновления и вставки, которые для основного сайта происходят только из-за регистрации. Эта довольно простая мера снизила нагрузку на наш сервер примерно на 80%.
источник
Что бы это ни стоило, кэширование в PHP - DIRT SIMPLE, даже без пакета расширения / помощника, такого как memcached.
Все, что вам нужно сделать, это создать выходной буфер, используя
ob_start()
.Создать глобальную функцию кеша. Вызов
ob_start
, передать функцию в качестве обратного вызова. В функции найдите кешированную версию страницы. Если существует, подайте его и закончите.Если он не существует, скрипт продолжит обработку. Когда он достигает соответствующего ob_end (), он вызовет указанную вами функцию. В это время вы просто получаете содержимое буфера вывода, помещаете его в файл, сохраняете файл и завершаете работу.
Добавьте в некоторые истечение / сборка мусора.
И многие люди не понимают, что вы можете вкладывать
ob_start()
/ob_end()
звонить. Так что, если вы уже используете выходной буфер, скажем, для разбора рекламных объявлений или подсветки синтаксиса или чего-то еще, вы можете просто вложить другойob_start/ob_end
вызов.источник
На самом деле, многие используют APC и memcached вместе ...
источник
Похоже, я был не прав . MySQLi все еще разрабатывается. Но, согласно статье, команда MySQL в настоящее время предоставляет PDO_MySQL. Из статьи:
Мне кажется, что статья смещена в сторону MySQLi. Я полагаю, что я склонен к PDO. Мне действительно нравится PDO поверх MySQLi. Это прямо для меня. API намного ближе к другим языкам, на которых я программировал. Интерфейсы OO Database, кажется, работают лучше.
Я не сталкивался с какими-либо конкретными функциями MySQL, которые не были бы доступны через PDO. Я был бы удивлен, если бы я когда-либо сделал.
источник
PDO также очень медленный, а его API довольно сложный. Никто в здравом уме не должен использовать его, если переносимость не является проблемой. И давайте посмотрим правде в глаза, в 99% всех веб-приложений это не так. Вы просто придерживаетесь MySQL или PostrgreSQL, или чего бы вы ни работали.
Что касается вопроса PHP и что принимать во внимание. Я думаю, что преждевременная оптимизация - корень всего зла. ;) Сначала сделайте свое приложение, постарайтесь сохранить его в чистоте, когда дело доходит до программирования, сделайте небольшую документацию и напишите модульные тесты. Со всем вышеперечисленным у вас не будет проблем с рефакторингом кода, когда придет время. Но сначала вы хотите закончить и вытолкнуть это, чтобы увидеть, как люди реагируют на это.
источник
Конечно PDO это хорошо, но там уже был какой - то спор о том, что это производительности по сравнению с MySQL и MySQLi, хотя это , кажется , теперь исправлена.
Вы должны использовать pdo, если планируете переносимость, но если нет, то mysqli должен быть подходящим. Он имеет интерфейс OO, подготовленные операторы и большую часть того, что предлагает pdo (за исключением переносимости).
Кроме того, если производительность действительно необходима, подготовьтесь к (родному mysql) драйверу MysqLnd в PHP 5.3, который будет гораздо более тесно интегрирован с php, с лучшей производительностью и улучшенным использованием памяти (и статистикой для настройки производительности).
Memcache хорош, если у вас есть кластерные серверы (и загрузка, похожая на YouTube), но я бы тоже сначала попробовал APC .
источник
Уже было дано много хороших ответов, но я хотел бы указать вам на альтернативный кэш кода операции под названием XCache . Это создано легким вкладчиком.
Кроме того, если в будущем вам может потребоваться балансировка нагрузки сервера базы данных, MySQL Proxy вполне может помочь вам в этом.
Оба эти инструмента должны легко подключаться к существующему приложению, поэтому эту оптимизацию можно выполнить, когда вам это нужно, без особых хлопот.
источник
Первый вопрос: насколько вы действительно этого хотите? И сколько вы планируете инвестировать в свою инфраструктуру. Поскольку вы чувствуете необходимость задать вопрос здесь, я предполагаю, что вы ожидаете начать с малого при ограниченном бюджете.
Производительность не имеет значения, если сайт недоступен. А для доступности вам нужно горизонтальное масштабирование. Минимум, с которым вы можете разумно обходиться, это 2 сервера, на которых работают apache, php и mysql. Настройте одну СУБД в качестве ведомой по отношению к другой. Выполните все операции записи на главном устройстве и все операции чтения в локальной базе данных (что бы это ни было) - если только по какой-то причине вам не нужно считывать только что прочитанные данные (используйте мастер). Убедитесь, что у вас есть оборудование для автоматического продвижения раба и ограждения хозяина. Используйте циклический DNS для адресов веб-сервера, чтобы придать большее значение подчиненному узлу.
Распределение ваших данных по разным узлам базы данных на этом этапе - очень плохая идея, однако вы можете рассмотреть возможность их разделения по разным базам данных на одном сервере (что облегчит разделение между узлами, когда вы обгоните Facebook).
Убедитесь, что у вас есть инструменты мониторинга и анализа данных для измерения производительности ваших сайтов и выявления узких мест. Большинство проблем с производительностью можно исправить, написав лучший SQL / исправляя схему базы данных.
Хранить кэш шаблонов в базе данных - глупая идея - база данных должна быть центральным общим хранилищем для структурированных данных. Храните кэш шаблонов в локальной файловой системе вашего веб-сервера - он будет доступен быстрее и не замедлит доступ к вашей базе данных.
Используйте кэш оп-кода.
Потратьте много времени на изучение вашего сайта и его журналов, чтобы понять, почему он работает так медленно.
Поместите как можно больше кэширования на клиента.
Используйте mod_gzip, чтобы сжать все, что вы можете.
C.
источник
Мой первый совет - подумать об этой проблеме и помнить об этом при разработке сайта, но не переусердствуйте . Зачастую сложно предсказать успех нового сайта, и я лучше потрачу ваше время на то, чтобы закончить рано и оптимизировать его позже.
В общем, Simple это быстро . Шаблоны замедляют вас. Базы данных замедляют вас. Сложные библиотеки замедляют вас. Слои шаблонов друг над другом, извлекая их из баз данных и анализируя их в сложной библиотеке -> время задержки умножаются друг на друга.
После того, как вы запустите основной сайт, проведите тесты, чтобы показать вам, на что вы можете потратить свои усилия. Трудно понять, на что нацеливаться. Часто, чтобы ускорить процесс, вам придется распутывать сложность кода, это делает его больше и сложнее в обслуживании, поэтому вы хотите делать это только при необходимости.
По моему опыту, установление соединения с базой данных было относительно дорогим. Если вы можете избежать неприятностей, не подключайтесь к базе данных для обычных посетителей на страницах с наибольшим объемом трафика, таких как главная страница сайта. Создание нескольких соединений с базой данных - это безумие с очень небольшой выгодой.
источник
@ Гэри
Сейчас я зациклен на PDO, и похоже, что вы правы - однако я знаю, что MySQL разрабатывает расширение MySQLd для PHP - я думаю, чтобы преуспеть либо в MySQL, либо в MySQLi - что вы об этом думаете?
@ Райан , Эрик , tj9991
Спасибо за совет по расширению кэширования PHP - не могли бы вы объяснить причины использования одного над другим? Я слышал замечательные вещи о memcached через IRC, но никогда не слышал о APC - что вы думаете о них? Я предполагаю, что использование нескольких систем кэширования довольно неэффективно.
Я определенно буду разбираться с некоторыми профилирующими тестерами - большое спасибо за ваши рекомендации по ним.
источник
В ближайшее время я не вижу, как я переключаюсь с MySQL - так что, мне кажется, мне не нужны возможности абстракции PDO. Спасибо за эти статьи DavidM, они мне очень помогли.
источник
Посмотрите на mod_cache , кэш вывода для веб-сервера Apache, аналогичный кешированию вывода в ASP.NET.
Да, я вижу, что это все еще экспериментально, но когда-нибудь оно станет окончательным.
источник
Я не могу поверить, что никто не упоминал об этом: модульность и абстракция. Если вы думаете, что ваш сайт должен будет вырасти до большого количества машин, вы должны разработать его так, чтобы он мог! Это означает, что такие глупые вещи, как не предполагать, что база данных находится на локальном хосте. Это также означает, что поначалу это будет беспокоить, например, написание уровня абстракции базы данных (например, PDO, но намного легче, потому что он делает только то, что вам нужно).
А это означает такие вещи, как работа с фреймворком. Вам понадобятся слои для вашего кода, чтобы впоследствии вы могли повысить производительность путем рефакторинга уровня абстракции данных, например, обучив его тому, что некоторые объекты находятся в другой базе данных - и код не должен знать или заботиться .
Наконец, будьте осторожны с интенсивными операциями с памятью, например, с ненужным копированием строк. Если вы можете уменьшить использование памяти PHP, то вы получите больше производительности от своего веб-сервера, и это будет масштабироваться, когда вы переходите к решению с балансировкой нагрузки.
источник
Если вы работаете с большими объемами данных, и кеширование их не сокращает, загляните в Sphinx. Мы получили отличные результаты, используя SphinxSearch не только для лучшего поиска текста, но и в качестве замены поиска данных для MySQL при работе с большими таблицами. Если вы используете SphinxSE (плагин MySQL), он превзошел наш прирост производительности, который мы получили от кеширования в несколько раз, и реализация приложения - это просто.
источник
Пункты, сделанные о кеше, точны; это наименее сложная и самая важная часть построения эффективного приложения. Я хотел бы добавить, что, хотя memcached - это здорово, APC работает примерно в пять раз быстрее, если ваше приложение работает на одном сервере.
В публикации «Сравнение производительности кэша» в блоге производительности MySQL есть несколько интересных тестов по этому вопросу - http://www.mysqlperformanceblog.com/2006/08/09/cache-performance-comparison/ .
источник