Игорь Олемской — практические заметки по системному администрированию Linux CentOS

Архив тега ‘highload’

Предотвращение двойного запуска cron задач (перепечатка)

Комментариев нет

Администрируя высоконагруженный проект, то и дело натыкаюсь на проблему повторного запуска cron задач в то время как предыдущая задача еще не отработала.

Таким образом получается, что одни и те же cron скрипты выполняют одни и те же задачи одновременно, удваивая тем самым нагрузку. При этом они начинают выполняться медленнее, и возможна лавинообразная ситуация, когда к этим двум добавится еще и третья такая же задача. Потом четвертая, а потом все упадет вообще.

Как с этим бороться?

Вариант 1. Сложный.

Использовать в скрипте, который запускается по cron, проверку pid:

  1. Проверяем наличие pid файла с идентификатором процесса
  2. Проверяем, есть ли такой pid в памяти командой «ps -p PID»
  3. Если pid запущен, прерываем работу
  4. Иначе, пишем в pid файл свой pid и продолжаем

Однако это требует модификации скрипта.

Вариант 2. Простой.

Есть замечательная утилитка в Linux, называется flock (1). В качестве параметра, утилита принимает имя файла лока и команду для исполнения. flock ставит эксклюзивный лок на указанный файл и, при успехе, запускает указанную команду. Функционал flock не ограничивается только этой возможностью – на эту тему можно покурить соответствующий man.

Итак, у нас есть cron задача:

* * * * *   user  /usr/bin/php /some/heavy/script.php

С помощью небольшой модификации этой строки мы сможем предотвратить повторный запуск задачи во время выполнения предыдущей задачи:

* * * * *   user  /usr/bin/flock -xn /var/lock/script.lock -c '/usr/bin/php /some/heavy/script.php'

Ну собсно все.

Оптимизация MySQL InnoDB на высоких нагрузках (перепечатка)

Один комментарий

Попытаюсь в этой статье рассказать об особенностях применения хранилища InnoDB в высоконагруженных проектах, а так же дать поверхностное сравнение MyISAM и InnoDB. Безусловно, MySQL не ограничивается только этими двумя типами хранилища данных, однако они являются подавляющими в своей распространенности использования.

Несмотря на то, что много в InnoDB для меня очевидно, все еще остаются некоторые темные пятна и если меня где то поправят, буду только благодарен.

Почему народ выбирает InnoDB? InnoDB обладает преимуществами перед MyISAM.

  1. Транзакционная модель. Это конечно преимущество не столько для администратора, сколько для программиста. Программист может объединить операции с базой в транзакцию, с кучей вытекающих из этого профита. Это основная причина по которой архитекторы выбирают InnoDB.
  2. Блокировка на уровне строки. В отличии от MyISAM, где идет блокировка на уровне таблицы, в InnoDB блокировка осуществляется на уровне строки. Проблема конкурентных блокировок стоит не так остро как в MyISAM, однако все таки присутствует. Но об этом ниже.
  3. Защита от сбоев. InnoDB более устойчивая к сбоям, если сказать точнее, InnoDB намного лучше восстанавливается после сбоев и практически не теряет данные. Для восстановления же MyISAM таблиц зачастую требуется потушить MySQL сервер и вручную восстанавливать таблицы утилитой myisamchk. Результатом работы myisamchk зачастую может оказаться частичная или полная потеря данных в таблице. InnoDB восстанавливается автоматически.
  4. Качественная работа с IO. InnoDB имеет свой собственный Buffer Pool в памяти, где держит таблицы. Для InnoDB можно отключить системную буферизацию IO при работе с таблицами InnoDB. Таким образом, можно сказать что в InnoDB нет двойной буферизации (как в MyISAM), следовательно, оперативная память разумно расходуется.

MyISAM конечно же тоже обладает преимуществами, в основном это простота и скорость. На небольших объемах данных и большом количестве операций чтения лучше хранилища не найти, если конечно вам не нужны транзакции. Но сейчас не об этом. На этой ноте про MyISAM больше ни слова.

InnoDB не готова корректно работать из коробки на высоких нагрузках. Надо хорошо понимать о происходящих в недрах InnoDB процессах дабы правильно настроить этот тип хранилища.

Ниже описаны ключевые моменты конфигурации, существенно влияющие на производительность.

innodb_file_per_table

По умолчанию, InnoDB использует общее хранилище для всех таблиц и индексов. Данная опция позволяет содавать на каждую таблицу свой .ibd файл. Наиболее частая причина применения этой опции – раскидать отдельные таблицы по отдельным физическим устройствам.

Так же бывают определенные таблицы, в которые очень часто пишутся и удаляются данные. Это серъезно фрагментирует общее хранилище таблиц и от этого может пострадать производительность других таблиц. В этом случае имеет смысл разбивать общее хранилище на отдельные куски для каждой таблицы.

Если у вас таблицы уже созданы в общем хранилище и вы перезагружаете сервер MySQL с этой опцией, старые таблицы останутся в общем хранилище, а новые будут создаваться в отдельных хранилищах.  Таким образом, чтобы поместить старые таблицы в раздельные файлы, нужно их пересоздать или переименовать.

Использование выделенных блочных устройств под хранилище

Киллер-фича InnoDB. Вы можете использовать целые партиции или физические устройства вместо файлов общего хранилища InnoDB. Это сразу убирает всякую системную буферизацию ввода-вывода и всякий оверхед файловой системы. В этом случае InnoDB пишет данные прямо на устройство. Конечно же, это создает ряд ньюансов в процедуре резервного копирования.

Для того чтобы использовать эту возможность, пропишите в конфигурации

[mysqld]
innodb_data_home_dir=
innodb_data_file_path=/dev/hdd1:3Gnewraw;/dev/hdd2:2Gnewraw

После старта InnoDB сделает инициализацию блочных устройств. Очень важно после этого остановить сервер и в конфигурации поменять «newraw» на «raw»:

[mysqld]
innodb_data_home_dir=
innodb_data_file_path=/dev/hdd1:3Graw;/dev/hdd2:2Graw

и перезапустить сервер. Иначе при следующем перезапуске, если InnoDB встретит «newraw», партиция будет заново отформатирована!

Так же надо иметь в виду, что пользователь, под которым запускается MySQL должен иметь права на запись в обозначенные партиции.

При использовании данной возможности, очевидно лучше для InnoDB выделять логические тома LVM. Это существенно упрощает бекап (по снятому снапшоту) и восстановление.

innodb_buffer_pool_size

Размер памяти, выделяемый под кеш данных и индексов. Строго говоря, чем больше таблиц сидит в этой памяти, тем лучше. Если есть возможность, размер этого буфера должен быть чуть больше общего размера innodb таблиц. Однако он не должен быть больше 80% объема ОЗУ.

innodb_log_file_size

Размер файла лога транзакций. Чем больше размер, тем реже InnoDB будет сбрасывать страницы Buffer Pool на диск, и тем больше требуется времени на восстановление после аварии. Размер варьируется от нескольких мегабайт до размера innodb_buffer_pool_size, но не более 4Gb суммарно во всех лог-файлах.

innodb_log_buffer_size

Размер буфера памяти для записи лога транзакций. Размер варьируется в пределах единиц-десятков мегабайт. Большой размер буфера позволяет запускать объемные транзакции без сброса лога на диск, что позволяет уменьшить IO при объемных транзакциях.

innodb_flush_log_at_trx_commit

Принимает одно из трех значений: 0, 1, 2. При значении 1, лог скидывается на диск при каждом коммите транзакции и буфер записи так же скидывается на диск. При 0 эта операция производится не при каждой транзакции а 1 раз в секунду. При значении 2, лог скидывается на диск при каждом коммите, но сброс буферов не производится.

Если вы ищете производительность в ущерб надежности – ставьте 0. Если наоборот – ставьте 1.

innodb_thread_concurrency

Количество рабочих тредов InnoDB. Начать надо с количества ядер CPU*2 + количество физических блочных устройств. Мне всегда этой формулы хватало. Официальная документация рекомендует поиграть с этим значением.

innodb_flush_method

Установка характера работы с файловой системой. Данная переменная не имеет эффекта при использовании выделенных блочных устройств под хранилище. Представляет из себя комбинацию значений O_DSYNC,O_DIRECT,fdatasync. Если вы используете большой размер innodb_buffer_pool_size, имеет смысл дать InnoDB доступ к файлам, минуя системные буфера с помощью опции O_DIRECT.

В официальном руководстве сказано, что при использовании определенных Storage Area Network, O_DIRECT может дать серъезный пенальти производительности.

Для OS GNU/Linux читайте про опции O_DSYNC (O_SYNC) и O_DIRECT на данной странице руководства open (2). FreeBSD очевидно имеет много сходств с GNU/Linux в этом вопросе.

Для OS MS Windows © ® ™ данная опция не имеет смысла, как и данная статья вообще.

innodb_locks_unsafe_for_binlog

Эта опция не может быть никак пропущена, если у вас серьезная нагрузка на конкурентную запись. Очень сложно это объяснить, да и не понимаю я этого до самой глубины, но если вкратце…

Если вам нужна полноценная изоляция транцакций, то эта опция не для вас. Тогда придется пренебрегать производительностью в пользу целостности транзакций.

Например, если вы используете чтение по диапазону (SELECT a FROM b WHERE c>100) внутри тразакции, то с включенной опцией innodb_locks_unsafe_for_binlog, следующий такой же запрос вернет тот же результат, даже если между ними кто то что то в эту таблицу пытался писать.

При выключенной (по умолчанию) опции innodb_locks_unsafe_for_binlog, во второй раз указанный запрос может вернуть отличный от первого раза результат в одной транзакции, поскольку пытающимся писать в эту таблицу процессам не было выставлено препятствий.

То есть, эта опция во включенном состоянии снимает туеву хучу локов при конкурентной записи-чтении в таблицы. Цена вопроса – не обеспечивается консистентный снапшот данных на время всей транзакции. Как то так в общем.

В моем случае, прирост производительности при включении этой опции был колоссальный. Однако это имеет смысл на реально массивных смешанных записях-удалениях-чтениях.

Ах да. И для репликации соответственно это не канает.

innodb_lock_wait_timeout

Довольно странная настройка, но она имеет место и является частой причиной потери данных. Когда тред ожидает снятия блокировки строки для модификации записей, он ожидает вплоть до указанного в этой опции количества секунд. По умолчанию это 50 секунд. Если за 50 секунд блокировка не была снята, транзакция отваливается с ошибкой

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

Если у вас нагруженный модификациями сервер, вы наверняка упретесь в это время ожидания и транзакции с изменениями данных будут завершаться с указанной ошибкой. В этом случае стоит подумать о включении опции innodb_locks_unsafe_for_binlog.

Программистов нужно предупреждать (если они не в курсе), что если они словили ошибку 1205 от InnoDB, то надо повторить или отложить транзакцию! Поскольку эта ошибка де-факто не может быть воспроизведена в тестовых условиях, очень часто программисты не в курсе и бывают весьма удивлены, наблюдая пробелы в потоках данных.

Конференция Highload++ 25 и 26 октября (перепечатка)

Комментариев нет

highload++

25 и 26 октября в Москве пройдет крупнейшая профессиональная техническая конференция Рунета — конференция разработчиков высоконагруженных систем HighLoad++. Мероприятие проходит уже четвертый год, собирая более 700 участников. В этом году основная направленность конференции — оригинальные исследования, новые архитектуры, новые концепкции и подходы в построении крупных Интернет-проектов.

HighLoad++ — знаковое событие по обмену опытом — мы ожидаем Stoyan Stefanov (Yahoo), Eugene Chigirinskiy (Microsoft), Patrice Pelland (Microsoft), James Golick, Robert Johnson (Facebook), Joe Damato, Петр Зайцев (Percona), Simon Riggs (PostgreSQL) и Bruce Momjian (PostgreSQL).

Joe Damato, “хакер”, специализирующийся на низком уровне, известный специалист в мире Ruby прочитает доклад “Настройка и инструментарий для Linux / Performance tweaks and tools for Linux”. Доклад разделен на две части. В первой части Джо рассмотрит особенности различных настроек производительности ядра Linux (и стандартные драйвера). Разговор пойдет о некоторых малоизвестных настройках ядра, подстройка которых поможет наиболее эффективно использовать аппаратные средства железа.

Во второй части доклада разговор пойдет о полезных инструментах для изучения и диагностики ошибок в процессах. Автор пробежится по различным инструментам для Linux (strace, ltrace, oprofile, gdb, и другие) и разберет, как их можно использовать, чтобы получить представление о том, на что тратятся ресурсы и время обработки запросов.

Другой отличный доклад — про архитектуру крупнейшего интернет-сайта в мире — Facebook.com от Robert Johnson, руководитель отдела разработки в Facebook, где он разрабатывает технологии по экономически эфективному масштабированию инфраструктуры и оптимизации производительности для миллионов пользователей Facebook.

Роберт расскажет о технологии, необходимой для запуска сайта таких масштабов (100 млрд. просмотров в день, 50 млрд. хранящихся фотографий), включая конкретные технологии созданные компанией Фейсбук, некоторые принципы, применяемые в работе с масштабированием, и уроки, полученные во время этих разработок. Также Роберт расскажет о наших новейших разработках в области масштабирования — пропуска социального контекста из сети через платформу Facebook.

Организаторы собрали в эти два дня крупнейшую встречу разработчиков баз данных — мы узнаем о новшествах в PostgreSQL и MySQL от тех, кто разрабатывал эти новшества: Саймон Ригс, Брюс Момжан, Петр Зайцев, разработчики Сфинкса, Константин Осипов и другие.

Целый блок докладов о Ruby и Python

  • Frontik. Сервер сборщик на python / Сергей Никулин (HeadHunter);
  • Оптимизация одного из топовых приложений для социальной сети ВКонтакте: 1000 запросов в секунду на Rails / Максим Лапшин;
  • Приемы разработки высоконагруженных приложений на Twisted / Андрей Смирнов;
  • Erlyvideo: 2000 одновременных видеоподключений / Максим Лапшин;

Облачные вычисления

  • Cloud APIs: обзор API западных провайдеров и API Scalaxy;
  • Extreme Cloud Storage on FreeBSD / Андрей Пантюхин;
  • Scaling to Hundreds of Millions of Requests: What Worked and What Didn’t / James Golick;

DDOS и защита от него

  • Тандемные DDoS-атаки / Проблематика уязвимостей в спецификации TCP/IP (фундаментальные уязвимости) / Артем Гавриченков;
  • Отчет за год по DDOS (атаки на ДНС, “не жадные” ботнеты, атаки на индекс Yandex (черный seo), высокоскоростные атаки, позиция государства и МВД на эту тему) / Александр Лямин;

Пара круглых столов

  • Квадратный стол про использование many-core CPU с участием Google, Intel, Yandex и Badoo / (Google, Яндекс, Mail.ru, Intel);
  • Круглый стол с представителями ВКонтакте;

Все доклады конференции построены как профессиональные — даже если докладчик рассказывает о своей услуге, он рассказывает о том, как она устроена, а не рекламирует ее. Например — “Как мы строим CDN в России”. Классификация CDN по спобу расположения серверов: расстановка серверов по сетям интернет-провайдеров или подключение к провайдерам в точках обмена трафиком. Классификация CDN по способу распределения нагрузки: DNS, HTTP Redirect. Классификация CDN по способу нахождения кратчайшего пути до пользователя.

И многое, многое другое — более 60 докладов из которых Программный комитет конференции, в который входят технические директора и ведущие специалисты крупнейших компаний Рунета (Яндекс, Mail.ru, Рамблер, Badoo и другие), выберет самые лучшие.

Подробности Вы можете найти на сайте конференции HighLoad++.

Google Bookmarks Digg I.ua Ru-marks Ruspace Zakladok.net Reddit delicious Technorati Yahoo My Web News2.ru БобрДобр.ru Memori.ru rucity.com

No related posts.

Удаленный шифрованный бэкап MySQL при помощи LVM snapshot (перепечатка)

Комментариев нет

Имеем: высоконагруженый MySQL сервер с таблицами объёмом более 20 Гб.

Требуется: ежедневное резервное копирование на удавленный хост с шифрованием данных

Условия: процедура бекапа не должна ни коим образом сказаться на производительности MySQL во время проведения оной.

Итак, mysqldump отпадает автоматически, ибо локи таблиц там испортят нам весь аптайм. Выбор пал на технологию LVM снэпшотов, доступную в любом линуксе, утилитку шифрования gpg, а так же IO scheduler CFQ.

Итак, подготовка.

1. Подготовка LVM.

Нам нужна LVM группа с необходимым свободным местом для:

  • Баз MySQL
  • LVM снэпшота

Т.е. объема свободного пространства в группе LVM должно быть под базы + где-то 10-20% (в зависимости от тяжести IO записи работы с базами).

Создаем LVM Physical Volume на девайсе /dev/sda2 (у меня /dev/sda это RAID5 из 6 SAS дисков, sda2 можете заменить на свой девайс):

pvcreate /dev/sda2

Создаем Volume Group с именем vg0 на /dev/sda2:

vgcreate vg0 /dev/sda2

Теперь надо создать в группе vg0 логический том (Logical Volume) под партицию MySQL таблиц с именем mysql.  У меня эта партиция занимает 500 Гб. При этом важно оставить в группе vg0 10-20% свободного места, не занятого логическими томами, дабы было возможно делать снэпшоты.

lvcreate -L 500G -n mysql vg0

Теперь наш девайс будет виден в:

/dev/mapper/vg0-mysql
/dev/vg0/mysql (symlink)

2. Подготовка ФС

Это, думаю, умеют делать все. Но на всякий напишу.

Делаем FS:

mke2fs -j -L lmysql /dev/mapper/vg0-mysql
mkdir /mysql

Прописываем в fstab:

LABEL=lmysql            /mysql                  ext3    defaults,noatime 0 0

Монтируем, подготавливаем:

mount /mysql
mkdir /mysql/myisam
chown mysql:mysql /mysql/myisam

Прописываем в /etc/my.cnf:

datadir=/mysql/myisam

Стартуем MySQL:

/etc/init.d/mysqld start

Дальше любимым путем переносим на этот раздел (/mysql/myisam) свои базы.

3. Подготовка MySQL

Надо пропатчить RC-скрипт MySQL для выделения высокого приоритета IO, дабы наша мышца не сдулась в ходе интенсивного бекапа.

Так же следует заметить, что я использую IO scheduler CFQ. Если у вас не CFQ, то можно забыть про приоритеты IO. Узнать/Выставить IO scheduler на девайсе можно в файле:

/sys/block/sda/queue/scheduler
(sda заменить на ваш девайс)

Смысл патча в том, чтобы после старта MySQL отдавать ему высокий приоритет IO в CFQ. Патч на CentOS 5 RC скрипт /etc/init.d/mysqld выглядит так. Думаю, народ разберется.

4. Подготовка авторизации

Я буду делать бекап через кучу пайпов. Причин две:

  • Так проще
  • tar накидывается на дисковое IO с меньшим энтузиазмом когда пишет в пайп | gpg | ssh, чем когда пишет на диск.

Конечно, это увеличивает продолжительность бекапа. Но и уменьшает вероятность затыка MySQL на время бекапа.

А по сему, мы создаем Беспарольную авторизацию по публичному ключу с хоста MySQL (юзер root) на ваш некий бекап-хост  user@backup.remotehost.com.

5. Скрипт бэкапа

Собственно скрипт состоит из двух частей. Я их сложил оба в /root/scripts/. И в скрипте backup.sh используется этот путь.

1. backup.php

Этот скрипт делает сброс таблиц MySQL на диск с READ LOCK. После лока он создает снэпшот тома /dev/vg0/mysql и после этого отпускает лок MySQL.

Скриптик это служебный, используется он из скрипта backup.sh.

В нем нужно поменять в строке коннекта к MySQL данные для коннекта рутового юзера к локальному серверу:

$link=@mysql_connect('localhost','root','');

Так же стоит обратить внимание на строку

exec("/usr/sbin/lvcreate --size 30G --snapshot --name $lv /dev/{$vg}/$part",$out,$ret);

А именно на 30G – это размер LVM снапшота. Нам он нужен на время бекапа, и размер снапшота должен превышать тот максимальный объем данных, которые MySQL сможет записать за это время на диск. Ну и конечно, в группе LVM vg0 должно быть именно столько или больше свободного места. 30G в общем за глаза.

2. backup.sh

А это именно тот скрипт, который будет запускаться из крона.

Он запускает backup.php для снятия снапшота, монтирует снапшот в указанную директорию, тарит раздел с таблицами, кидает это все в пайп к gpg для шифрования по алгоритму AES256 с симметричным ключом и кидает дальше в пайп ssh, который уже на удаленной стороне складывает с помощью dd все это хозяйство в файл бекапа с временной меткой. Фух.

Далее он размонтирует снапшот и удаляет его.

Если кто успел заметить, используется утилита gpg для шифрования симметричным ключом, который расположен в файле $keyfile. Данный файл должен содержать около 20 случайных ASCII символов одной строкой. Стоит заметить что нужно создать этот файл раз и навсегда и сохранить где то у себя его копию, поскольку расшифровать бекап можно будет только с его помощью. А сделать это можно будет сделать командой:

gpg --passphrase-file $keyfile --cipher-algo AES256 -d file.tgz.gpg > file.tgz

Прочие переменные:

gpgpath – путь к gpg, с завершающим слешем
vgname – имя группы LVM, содержащей том с таблицами MySQL
lvname – имя тома создаваемого снапшота
partitionlvname – имя тома с таблицами MySQL в группе $vgname
mntpoint – директория для монтирования снапшота
remotehost – юзер и хост для удаленного бекапа (см. пункт 4)
f — имя файла, в который на удаленной стороне будет складываться шифрованный бекап

Собственно, все. Удачного дебага всего этого хаоса что выше ))

 

Логирование медленных запросов Apache

Комментариев нет

Для логирования медленных запросов Apache очень удобно использовать модуль mod_log_slow, домашняя страница которого находится по адресу http://code.google.com/p/modlogslow/

Для установки модуля под CentOS 5 64bit можно воспользоваться репозиторием Southbridge:

yum install modlogslow

или установить пакет по прямой ссылке:

rpm -ihv http://rpms.southbridge.ru/stable/x86_64/modlogslow-1.0.6-1.southbridge.x86_64.rpm

Пример конфигурации можно посмотреть в файле /etc/httpd/conf.d/logslow.conf

13.03.2010

Написал Игорь Олемской