Разработка на коленке
История оптимизации двух
маленьких проектов
А давайте напишем маленький
скрипт
• Пользователю могут выдаваться очки
• Очки можно поменять на бонус
• Возможность посмотреть баланс
• Нет баланса – нет учетки
• Ответы реализованы в виде http codes
(вроде как REST)
LAMP
• PHP
• Apache (mod_php, mod_rewrite)
• MySQL (куда же без него)
Выгрузились,
запустились,
всё работает,
клиенты ходят,
данные передаются
Первая проблема
• Возрастает количество
клиентов и MySQL
начинает потреблять
всё больше
процессорных ресурсов,
хотя slow query log
пустой.
• Проблема в частых
запросах к маленькой
табличке. Запросы
выполняются быстро
(менее 1 секунды), но
нагружается процессор.
Но ненадолго
Выгрузка нового билда
мобильного приложения
• Возникает проблема, когда клиент
начинает обращаться к серверу
несколько раз в секунду вместо одного
раза в 10 минут.
• Клиентов достаточно много, получаем
DDOS атаку.
Основные проблемы
• MySQL начинает сбрасывать
соединения.
• Apache начинает проявлять
прибалтийские кооорни.
Пути решения
• Увеличение мощности сервера
• Кэширование (memcached).
• Изменяем порядок обработки запросов
на php
Увеличение мощности сервера
• Поскольку дело было на Amazon,
увеличение мощности произошло с
помощью одного клика мыши.
Кэширование
• Самым частым запросом оказался
запрос на получение учетной записи
клиента. Однако для большинства
запросов учеток не было. Пришлось
кэшировать в memcache все ответы.
• Данные о пользователях сохранялись
по предсказуемым ключам.
• На MySQL Query Cache не
рассчитывали
Изменение порядка обработки
запросов на php
• Поскольку apache все равно не
выдерживал потока запросов, было
принято решение заменить его на
nginx+php-fpm (не только потому что его
использовать круто, а apache нет)
• Установка APC
Результаты
• Увеличение обслуживаемых rps больше
чем в два раза
• Падение нагрузки на сервер
• 99.9% hits в memcache
• Снижение нагрузки на дисковую
систему
• Нет ситуации с долгим ожиданием
ответа
Второй проект
• Сеть для показа рекламы
• Нужно было написать не маленький
скрипт, а мини систему управления
контентом.
• Клиенты делают запросы и тянут
рекламу с сервера.
Опять же Lamp
• PHP
• Apache
• MySQL
Опять же всё написано,
выгружено и вроде даже
стабильно работает, статистика
пишется и все происходит в
режиме реального времени
Первые проблемы
• Подсчет статистики
при показе списка
• Кэширование с
пересчетом раз в
полчаса
Появление новых возможностей
• Новые типы рекламы по запросу
• Начинаем собирать информацию о
пользователях ( взаимодействие с
приложениями - клиентами )
• Добавление рассылок push notifications
• Деление пользователей на группы
• Возможность фокусирования всех
типов реклам на отдельного
пользователя.
И вдруг одно из мобильных
приложений выводят в top и
буквально сразу же начинаются
проблемы с
производительностью серверной
части
Результаты вывода в top
• Много установленных приложений –
много запросов к системе (К.О. или таки
уже майор?)
• Приложения-будильники стартуют в
одной часовой зоне практически
одновременно (разбежка часов очень
небольшая)
• Apache забивается запросами статики
Что применялось
• Nginx
• Memcached
• Изменения в исходном коде
• APC
Nginx
• Отдача статики для всех проектов на
данном сервере
• Обратное проксирование
Memcached
• Компромисс между мгновенным
отражением изменений данных и
производительностью системы.
• Кэширование редко изменяющихся
данных
Изменения в исходном коде
• Проверка некоторых условий на
актуальность до главного запроса
• Изменение кода для избежания
deadlocks в MySQL.
Результаты
• Улучшение производительности, т.к. На
отдачу статики не расходуются ресурсы
apache
• Улучшение ситуации при работе с
медленными клиентами.
• Снижение нагрузки на MySQL.
Общие рекомендации
Отделение часто изменяемых
данных, от тех данных, которые
меняются редко. В частности это
упрощает создание эффективной
системы кэширования. Например
отделение информации о
пользователе от его баланса
Для упрощения поддержания
кэша в адекватном состоянии
стоит использовать
предсказуемые ключи,
например для пользователя
userdata_{id}
В некоторых случаях можно
отражать изменения с некоторой
задержкой
Кэширование не должно
использоваться как костыль для
решения проблем приложения (а
иногда так хочется).
В первую очередь кэширование
стоит применять для данных,
которые редко меняются.
MySQL query cache vs
кэширование на стороне
приложения.
Как правило, при кэшировании
всегда доступна операция delete.
В некоторых случаях имеет
смысл использовать постоянные
соединения (persistent
connections), однако надо
помнить, что некоторые модули
чистят состояние соединения
(mysqli), а некоторые – нет
(PDO).

Development on the Knee by Vladimir Khramtsov

  • 1.
    Разработка на коленке Историяоптимизации двух маленьких проектов
  • 2.
    А давайте напишеммаленький скрипт • Пользователю могут выдаваться очки • Очки можно поменять на бонус • Возможность посмотреть баланс • Нет баланса – нет учетки • Ответы реализованы в виде http codes (вроде как REST)
  • 3.
    LAMP • PHP • Apache(mod_php, mod_rewrite) • MySQL (куда же без него)
  • 4.
  • 5.
    Первая проблема • Возрастаетколичество клиентов и MySQL начинает потреблять всё больше процессорных ресурсов, хотя slow query log пустой. • Проблема в частых запросах к маленькой табличке. Запросы выполняются быстро (менее 1 секунды), но нагружается процессор.
  • 6.
  • 7.
    Выгрузка нового билда мобильногоприложения • Возникает проблема, когда клиент начинает обращаться к серверу несколько раз в секунду вместо одного раза в 10 минут. • Клиентов достаточно много, получаем DDOS атаку.
  • 8.
    Основные проблемы • MySQLначинает сбрасывать соединения. • Apache начинает проявлять прибалтийские кооорни.
  • 9.
    Пути решения • Увеличениемощности сервера • Кэширование (memcached). • Изменяем порядок обработки запросов на php
  • 10.
    Увеличение мощности сервера •Поскольку дело было на Amazon, увеличение мощности произошло с помощью одного клика мыши.
  • 11.
    Кэширование • Самым частымзапросом оказался запрос на получение учетной записи клиента. Однако для большинства запросов учеток не было. Пришлось кэшировать в memcache все ответы. • Данные о пользователях сохранялись по предсказуемым ключам. • На MySQL Query Cache не рассчитывали
  • 12.
    Изменение порядка обработки запросовна php • Поскольку apache все равно не выдерживал потока запросов, было принято решение заменить его на nginx+php-fpm (не только потому что его использовать круто, а apache нет) • Установка APC
  • 13.
    Результаты • Увеличение обслуживаемыхrps больше чем в два раза • Падение нагрузки на сервер • 99.9% hits в memcache • Снижение нагрузки на дисковую систему • Нет ситуации с долгим ожиданием ответа
  • 14.
    Второй проект • Сетьдля показа рекламы • Нужно было написать не маленький скрипт, а мини систему управления контентом. • Клиенты делают запросы и тянут рекламу с сервера.
  • 15.
    Опять же Lamp •PHP • Apache • MySQL
  • 16.
    Опять же всёнаписано, выгружено и вроде даже стабильно работает, статистика пишется и все происходит в режиме реального времени
  • 17.
    Первые проблемы • Подсчетстатистики при показе списка • Кэширование с пересчетом раз в полчаса
  • 18.
    Появление новых возможностей •Новые типы рекламы по запросу • Начинаем собирать информацию о пользователях ( взаимодействие с приложениями - клиентами ) • Добавление рассылок push notifications • Деление пользователей на группы • Возможность фокусирования всех типов реклам на отдельного пользователя.
  • 19.
    И вдруг одноиз мобильных приложений выводят в top и буквально сразу же начинаются проблемы с производительностью серверной части
  • 20.
    Результаты вывода вtop • Много установленных приложений – много запросов к системе (К.О. или таки уже майор?) • Приложения-будильники стартуют в одной часовой зоне практически одновременно (разбежка часов очень небольшая) • Apache забивается запросами статики
  • 21.
    Что применялось • Nginx •Memcached • Изменения в исходном коде • APC
  • 22.
    Nginx • Отдача статикидля всех проектов на данном сервере • Обратное проксирование
  • 23.
    Memcached • Компромисс междумгновенным отражением изменений данных и производительностью системы. • Кэширование редко изменяющихся данных
  • 24.
    Изменения в исходномкоде • Проверка некоторых условий на актуальность до главного запроса • Изменение кода для избежания deadlocks в MySQL.
  • 25.
    Результаты • Улучшение производительности,т.к. На отдачу статики не расходуются ресурсы apache • Улучшение ситуации при работе с медленными клиентами. • Снижение нагрузки на MySQL.
  • 26.
  • 27.
    Отделение часто изменяемых данных,от тех данных, которые меняются редко. В частности это упрощает создание эффективной системы кэширования. Например отделение информации о пользователе от его баланса
  • 28.
    Для упрощения поддержания кэшав адекватном состоянии стоит использовать предсказуемые ключи, например для пользователя userdata_{id}
  • 29.
    В некоторых случаяхможно отражать изменения с некоторой задержкой
  • 30.
    Кэширование не должно использоватьсякак костыль для решения проблем приложения (а иногда так хочется).
  • 31.
    В первую очередькэширование стоит применять для данных, которые редко меняются. MySQL query cache vs кэширование на стороне приложения.
  • 32.
    Как правило, прикэшировании всегда доступна операция delete.
  • 33.
    В некоторых случаяхимеет смысл использовать постоянные соединения (persistent connections), однако надо помнить, что некоторые модули чистят состояние соединения (mysqli), а некоторые – нет (PDO).