От стартапа до highload: Эволюция веб

реклама
От стартапа до highload:
Эволюция веб-проекта, или
Как победить нагрузку
Антон Терехов
Ведущий инженер - программист отдела фотосервисов
ООО "Медиа Мир" (РБК)
PhotoFile. Начало.
• Проект получен в 2005 году
• Проект состоял из 2-х серверов: www + DB, fileserver
• Количество записей в БД:
– Пользователи:
– Альбомы:
– Фото:
~80 000
~290 000
~6 500 000
• Нагрузка: хиты ~2 000 000 хосты: ~55 000
• Файловый сервер заполнен на 3/4
• Что делать?
PhotoFile. Начало.
Улучшили, то, что можно улучшить быстро:
• Вынос DB на отдельный сервер
• Регистрация пользователей на новом fileserver’е
• Включение Smarty caching
• И, конечно же, начали делать версию 2 
Новый движок
• Это – фотохостинг. Мы не меняем URL изображения.
(Только если пользователь сам не сделает что-то с фото)
•
•
•
•
•
URL вида photofile.ru/photo/userlogin/albumid/photoid.jpg
ЧПУ – залог удобства ресурса
photofile.ru/users/userlogin/…
Все фото пользователя хранятся на 1 сервере, что
исключает работы по переносу файлов между машинами
При отказе сервера внешние ссылки не изменяются
nginx разпределяет запросы к fileserver’ам (regexp)
Появляется отдельный proxy-server
Реклама – зло!
• HTTP 1.1 500 Нагрузка растет
• Введение MySQL Master-Slaves
• Код не готов - введение отдельного сервера для
авторизованных пользователей http://a.photofile.ru/
–
–
–
+
Временное неправильное решение
Нет отказоустойчивости
Разные ссылки для авторизованного и анонимного пользователей
Но зато оно работает!
Новый движок. Часть 2.
• Старые URL фото вида
ff01.photofile.ru/photo/056/290/1239173/128169725442ea9efd115a.jpg
• Новые URL фото вида
photofile.ru/photo/UserLogin/AlbumID/Photo.jpg
+ Уменьшается количество полей в таблице
+ Упрощение ссылок
+ Более четкая дисковая структура
photo/U/Us/UserLogin/
+ Мы можем выделить на подмножество пользователей (Us)
отдельный fileserver!
– URL фото в альбоме можно подобрать (Bruteforce). Нужна новая
система паролирования альбомов.
ngnix: X-Accel-Redirect и md5(то, что меняется между клиентами)
Проблемы с версией 2
(которые можно было предусмотреть)
• Smarty cache – «неидеальное» решение для нескольких
frontends + fileservers
– Некогерентен
– Невозможно удаление «по событию»
– NFS на файлы Smarty cache является SPOF (и не используется)
• БД «не держит» нагрузку
– Слишком большая таблица альбомов
– Слишком много сортировок и условий
+ Таблица типа MRG + Cron script
(album_new – за последние 2 месяца, album_old – все остальные)
These Aren't the Droids You're looking For
• «Старые» ссылки на файлы при переносе = symlinks
• «Старые» ссылки на страницы и файлы =
денормализованные таблицы + «правильные» индексы
• При кажущейся непервоочередности проблемы –
пользователи не почувствовали себя «лишними»
Что делать?
• Cache Smarty не эффективен
• Очевидное решение – memcached
– Данные не связаны между собой
– Не гарантирует хранение
• Необходим дополнительный уровень абстракции метаданные
Memcached with METAinformation
+ Реализация SQL limit
+ Уменьшение данных для
сериализации
+ Единовременное
устаревание коллекции
данных
+ Самостоятельная
обработка устаревания
− Дополнительные
операции get/set
Файловые транзакции
• Выросший объем файлов в альбоме
• Необходимы real-time операции
• Обернем каждую файловую операцию в транзакцию (SQL
и диск)
• Сократим дисковые операции путем введения флага
«удален»
• nginx:
set $flag /...../.deleted
if ( -f $flag ) {
return 404;
}
Предел MySQL Master-Slaves
• Данных меньше не становится
• Эффективное количество Slaves конечно
• Решение – разделить данные на несколько порций
–
–
–
–
Управляющая часть (список пользователей, сессии)
Данные пользователя (альбомы, фотографии)
Общие данные (форум, конкурсы)
Справочники (пункты печати)
• Вопросы:
– Как сохранить существующий формат ID
– Как организовать Autoincrement
– Балансировка нагрузки
Сквозой autoincrement по нескольким
mysqld
4 294 967 295 :
например
M = 50 частей, по 85 899 345
20 INSERT/сек
Заполнение части: 49 дней
Работа с разделенными данными
• На каждую порцию
данных есть 2 Slaves
• При подключении
указываем режим работы
R или RW
• Балансировка путем
анализа нагрузки и
размещения на сервере
нескольких баз или же
демонов (разные порты,
репликация)
Распределение файлов по серверам
•
•
•
•
•
Более 40 fileservers x 1.4Tb
REGEXP слишком сложен
Часть данных превышает 1.4Tb
Dynamic DNS – наш выбор
Nginx.conf:
resolver
127.0.0.1;
resolver_timeout
1s;
…
set $username $1;
proxy_pass
http://$username.photofile$request_uri;
Photofile в цифрах и фактах
Сервера:
Proxy:
www (php):
MySQL:
Fileserver
Backup
Прочие
Итого:
2
7
13
55
55
3
135
Посещаемость:
Хиты: 4 500 000
Хосты: 200 000
В базе:
Пользователей: 1 000 000
Альбомов: 2 100 000
Фото: 70 000 000
Вместо итогов
• Что еще используется:
– CARP – разделение IP для
резервного проксирования
– mod_accel – для
кеширования частых URL
– nginx кеширует популярные
фото
– MySQL Master-Slaves для
разделения запросов на
«запись-чтение»
– Cron & rsync – для
генерации статического
контента
• Что планируется:
– Ввод дополнитетельных
файлов-флагов
«запаролен», «защищен»
– Переработка отдачи
картинок (вынос preview на
отдельные сервера)
+ 55 fileservers, +55 backup
От стартапа до highload:
Эволюция веб-проекта, или
Как победить нагрузку
Вопросы?
Антон Терехов, ведущий инженер-программист
[email protected]
Скачать