Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Облако в Badoo год спустя

1,379 views

Published on

Доклад на highload++ в 2014 про «облако» в Badoo

Published in: Technology

Облако в Badoo год спустя

  1. 1. «Облако» в Badoo год спустя Юрий Насретдинов
  2. 2. О компании 225M пользователей 4M загрузок фото в день 40K RPS на PHP-FPM 2K серверов 160K регистраций в сутки 50 языков интерфейса
  3. 3. О чём доклад • Общая архитектура: история создания, распределение нагрузки, отказоустойчивость. • Логи скриптов: сбор, индексация, различные виды просмотра. • Влияние Google App Engine — «облачный» разборщик очередей. • Планы на будущее • Как мы бы реализовали «облако» сейчас
  4. 4. Стек технологий • OS — SLES (SUSE Linux Enterprise Server) • ЯП — PHP 5.5, C/C++, Go, Java • Базы данных — MySQL, Tarantool, SQLite • Кеширование — Memcached • Веб-сервер — Nginx
  5. 5. Общая архитектура • «Старая система»: mcron — утилита для раскладки crontab по машинам • Общая архитектура новой системы («облака») • Распределение нагрузки по машинам, «попугаи» • Способы обеспечения отказоустойчивости
  6. 6. mcron sendSMS.php anonChat.php #1 moderation.php config facebook.php anonChat.php #2 errorlogs.php scripts1 scripts2 translate.php anonChat.php #9 cleanup.php scripts50 …
  7. 7. mcron sendSMS.php anonChat.php #1 moderation.php config facebook.php anonChat.php #2 errorlogs.php scripts1 scripts2 translate.php anonChat.php #9 cleanup.php scripts50 …
  8. 8. mcron sendSMS.php facebook.php anonChat.php #1 moderation.php config google.php anonChat.php #2 anonChat.php #3 migration.php scripts1 scripts3 translate.php errorlogs.php anonChat.php #9 cleanup.php scripts50 …
  9. 9. Недостатки старой системы • Ручное распределение нагрузки по серверам • Ручной перенос скриптов с «упавших» машин — очень большой downtime • Наличие «особенных» машин, на которых установлен дополнительный софт
  10. 10. «Облако» • Запуск заданий по расписанию / через API • Автоматическая балансировка нагрузки • Отсутствие «особенных» машин (на всех машинах стоит весь необходимый софт) • Отказоустойчивость к «падению» машин — автоматический перезапуск после таймаута
  11. 11. «Облако» (для разработчика)
  12. 12. «Облако» (для разработчика) script job #1 job #2 job #3 job #4 job #5
  13. 13. Архитектура MySQL MySQL cloudsys1 cloudsys2 cloud1 • • • cloudN Легенда: master replication mysql phproxyd heartbeat
  14. 14. «Облако» • Около 1 000 машин* • 15K SQL RPS (50/50 read/write) • 1 000 запусков скриптов в секунду • «Запускалка» на PHP, 16 процессов • Планировщик на go * Цифры приведены для 1 ДЦ, у нас их 2
  15. 15. Планировщик PHP Go
  16. 16. Балансировка нагрузки 1000 300 600 250 2000 230 1000 200 2000 180 weighted round-robin
  17. 17. Балансировка нагрузки
  18. 18. Отказоустойчивость • MySQL — ручное (!) переключение на slave в случае аварии • Управляющая логика работает «циклами» — перед началом цикла берется лок в базе, по окончании цикла лок отпускается • Если машина «упала» в середине цикла, то через wait_timeout на сервере соединение будет разорвано и, соответственно, отпущен лок, давая возможность работать логике другой машине
  19. 19. Отказоустойчивость • По умолчанию wait_timeout составляет 8 часов… • Мы выставили wait_timeout = 60 сек • Cпецифичная для Percona настройка innodb_kill_idle_transaction = 60 сек • Таким образом, при любых проблемах с сетью или с машинами, максимальный простой управляющей логики составляет 1 минуту
  20. 20. Отказоустойчивость • «Задания» запускаются с лимитом на максимальное время их работы, который задает пользователь • При наступлении лимита скриптами присылается SIGTERM • Если машина не отвечает — скрипт сам «погибает» от SIGALRM, поскольку при запуске скрипта мы вызываем alarm(макс.время работы + 3 секунды) • Часы на всех машинах идут с точностью до 1 секунды
  21. 21. Сбор логов • Каждое задание получает уникальный id • Задание — запуск скрипта, с перенаправлением вывода в файлы «logs/phproxyd.<id>.(out|err).log» • С помощью inotify слушаем изменения в директории с логами и отправляем новые строки в scribe • С задержкой доставки scribe (несколько секунд) логи скапливаются на отдельной logs-машине
  22. 22. Просмотр логов • Логи для каждого скрипта складываются в отдельный файл • Файлы «ротируются» (с использованием logrotate) раз в неделю • Каждая строчка в логе содержит id запуска и hostname, где скрипт запускался • Логи «индексируются» в MyISAM-таблички для быстрого просмотра истории по конкретному id
  23. 23. Разборщик очередей • У нас все «важные» очереди хранятся в MySQL, для сохранности и транзакционности посылки событий • В MySQL довольно тяжело «правильно» разбирать очереди во много потоков
  24. 24. Разборщик очередей • Существует много стратегий «разбора очереди» в MySQL: • 1) SELECT … WHERE id % N = M • 2) UPDATE … SET instance_id = N WHERE instance_id IS NULL • 3) SELECT … WHERE shard_id = N
  25. 25. Разборщик очередей • Почти все стратегии плохо масштабируются при увеличении числа воркеров • Подход с shard_id масштабируется, но нужно следить за равномерностью распределения + требуется решардинг при смене числа воркеров • Решили написать обработчик очереди, используя API по добавлению заданий в «облако»
  26. 26. Разборщик очередей • Реализация: На каждую очередь создается 2 «скрипта»: • 1) мастер, который выбирает id новых событий из очереди (однопоточный) • 2) воркеры, которые обрабатывают пачки заданий (получают набор id заданий, которые нужно обработать) • Мастер «помнит» все id, которые он уже выдал и выбирает из очереди с помощью SELECT id … NOT IN(…)
  27. 27. Разборщик очередей • Мастер группирует события в «пачки» для большей эффективности обработки • Равномерное распределение по воркерам • Динамическое число воркеров (on demand) • Можно сделать такой разборщик без API, через fork(), со всеми воркерами на одной машине
  28. 28. Причины «падений» • Суммарный downtime системы составил 3 часа за год эксплуатации, что дает uptime 99,97%: • 1 час — Duplicate key в MySQL :) • 1 час — «кривой» merge (неправильно разрешены конфликты) — забыли прогнать тесты • 30 минут — «сломанный» cron на машинах (баг в одной из версий vixie cron) — не отправлялся heartbeat
  29. 29. Проблемы MySQL • Основные проблемы возникают из-за глобальных mutex’ов или однопоточных подсистем: • Медленный DROP TABLE больших таблиц — перед unlink() берется глобальный metadata lock и «висят» все транзакции
  30. 30. Проблемы MySQL • Медленный (однопоточный) purge thread — из-за MVCC «удаленные» записи могут очень медленно «пуржиться» из таблиц — в InnoDB возможна ситуация, когда SELECT COUNT(*) из «пустой» таблицы идет минуты и возвращает 0 • Однопоточная репликация (до MySQL 5.6) — изменения могут не успевать применяться на реплике
  31. 31. Проблемы MySQL • Высокие накладные расходы на подключение — MySQL плохо «держит» больше N подключений, где N составляет 2-3 тысячи • В новых версиях MySQL и в MariaDB есть «connection pooling», причём для MySQL эта возможность отсутствует в Community Edition
  32. 32. Проблемы ядра Linux • Баг с выводом ps и «[migration/N]», который якобы «ест 100% CPU» (на самом деле не ест) • Очень медленный unlink() больших файлов, даже с ext4 (возникает из-за высокой фрагментации) • «Плохая» реализация inotify — если в директории активно создают файлы и у вас много «свободной» ОЗУ, inotify_add_watch() будет занимать секунды (!) и полностью блокировать запись в эту директорию
  33. 33. Планы на будущее • Полностью перевести управляющую логику на Go: иметь по одной goroutine на машину «облака» — одна «затупившая» машина не будет тормозить обработку остальных заданий • Перевести phproxyd на PHP (уже написан, нужно запустить в production) — экономия на запуске интерпретатора • Возможно, открыть исходные тексты системы
  34. 34. Как бы мы реализовывали сейчас • Управляющая логика на Go — отличный выбор, если вы почему-то не любите Erlang • Хранение текущего состояния заданий — Tarantool + Lua процедуры • Сразу написать новый демон для запуска заданий вместо существующего (на PHP, конечно же)
  35. 35. Вопросы Юрий Насретдинов @YNasretdinov y.nasretdinov@corp.badoo.com

×