Как прошел selectel.meetup

selectel.meetup

17 декабря в Санкт-Петербурге впервые прошел selectel.meetup — встреча, посвященная высоконагруженным системам. Чтобы обменяться опытом, разработчики собрались в одном из дата-центров Selectel — мы принимали гостей в новом конференц-холле. Генеральным партнером мероприятия стала компания ITSumma (техническая поддержка сайтов и удаленное администрирование серверов).

Участники выступили на selectel.meetup со следующими докладами:

  • Вячеслав Ахметов (Selectel) — «Эволюция memcache в высоконагруженных проектах»;
  • Мехти Мусаев (Selectel) — «Метрики кода: зачем они нужны»;
  • Евгений Потапов (ITSumma) — «Преждевременная оптимизация архитектуры»;
  • Сергей Спорышев (ITSumma) — «Как создавался Project1917 и как мы выдерживаем 1000 RPS на одном сервере»;
  • Алекс фон Розен (220 Вольт) — «Highload на скорую руку»;
  • Виктор Смирнов (220 Вольт) — «Двадцать семь пятниц на неделе»;
  • Ян Ашенкампф (KupiVip.ru) — «Как мы KupiVIP переписывали»;
  • Илья Пятин (CarPrice) — «Как два года подряд обеспечивать безудержный рост функциональности проекта»;
  • Сергей Аверин (Acronis) — «Распространенные ошибки применения баз данных»;
  • Артем Гавриченков (QRator Labs) — «Оценка рисков DDoS-атак».

Пока готовится видео с конференции, публикуем краткий обзор докладов представителей Selectel.


Мехти Мусаев: «Метрики кода: зачем они нужны»

Метрики кода служат для получения численного значения некоторого свойства программного обеспечения и его характеристики. Первые метрики кода, которые появились в начале 1970-х годов, служили для определения качества программного обеспечения и выявления ошибок или уязвимых мест в программном коде. Впоследствии, когда теоретическая и практическая информатика начала развиваться большими темпами и в разных областях, метрики создавались для других нужд. Например, они могут служить для определения качества обфускации программного обеспечения.

Наибольшую популярность сейчас имеют метрики кода для выявления качества программного кода. Они служат для планирования проекта, определения размера программного кода, сложности ПО и оценки усилий на его разработку. Сегодня используются следующие метрики: покрытие кода тестами (code coverage), связность (cohesion), цикломатическая сложность или сложность Мак-Каби (cyclomatic complexity or McCabe’s complexity), сложность Холстеда (Halstead complexity), индекс ремонтопригодности/поддержания программного обеспечения (Maintainability index) и строковые метрики (raw metrics).

Метрика покрытия кода тестами пользуется наибольшей популярностью ввиду потребности писать тесты для ПО. Они показывают в процентах покрытие тестов программным кодом. Чем выше метрика покрытия кода, тем больше исполняется программного кода при запуске тестов и, следовательно, — меньше вероятность содержания невыявленных ошибок в ПО.

Связность показывает степень с которой элементы модуля взаимосвязаны между собой. Чем выше связность, тем сильнее система взаимодействует между собой.

Цикломатическая сложность (или сложность Мак-Каби) разработана Томасом Мак-Каби в 1976 году и показывает структурную сложность программы. Она позволяет через граф потока управления определить сложность программы. Интересной особенностью данной метрики является то, что она вычисляется через граф потока управления программы. Более подробно — это количественная мера числа линейно независимых маршрутов в исходном коде программы. Эту метрику также можно применять отдельно для функций, модулей, методов и классов программы.

Метрика Холстеда была опубликована в 1977 году, её цель — идентифицировать измеримые свойства ПО и взаимосвязи между ними.

Индекс ремонтопригодности служит для определения решения по поддержанию ПО. Она вычисляется из строковых метрик, цикломатической сложности и сложности Холстеда. Имеет популярность в некоторых интегрированных средах разработки ПО (таких, как MS Visual Studio).

Строковые метрики показывают наличие физического и логического кода и числах.


Вячеслав Ахметов: «Эволюция memcache в высоконагруженных проектах»

Как обычно происходит внедрение и развитие memcache в архитектуре. Обычно, для экономии берется один сервер и на нем поднимается база и само приложение — помимо экономии такое соседство дает хорошую производительность благодаря отсутствию сетевых задержек.

При росте нагрузки обычно разносят приложение с базой по разным серверам. Но раз уж доклад про memcache, то мы сначала добавим уровень кэширования (благодаря этому мы можем снизить нагрузку на базу данных), но база со временем всё равно растет и мы её всё таки выносим на отдельный сервер (или съезжает приложение с кэшем).

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

Для решения этих проблем мы выносим кэш на отдельный сервер. Всё становится вроде бы хорошо, но сложности возникают, когда мы не можем уже вертикально масштабировать кэш или просто не готовы иметь SPOF в архитектуре.

Теперь рассмотрим варианты масштабирования и их проблемы.
Для начала нам надо научить все инстансы приложений работать с одним и тем же списком кэш серверов. Все современные memcache-клиенты имеют базовые алгоритмы шардинга ключей: Modulo и Ketama (Consistent Hashing). Оба этих алгоритма разделяют схожую идею распределения ключей между серверами, которую можно изобразить следующим образом:

servers = [’server1:11211′, ’server2:11211′, ’server3:11211′]
server_for_key(key) = servers[hash(key) % servers.length]

Проблемы:
добавление или удаление сервера ведет к промахам/потере;
изменения надо производить одновременно на всех инстансах приложений (иначе будет неконсистентность данных);
временное пропадание одной из нод допускает неактуальность данных.

Что с этим можно сделать?
В бета-ветке memcached 1.6 был добавлен алгоритм vbucket. Ключевое отличие vbucket от Ketama в том, что ключи мапятся не к серверам, а к фиксированному количеству логических сущностей «виртуальных корзин». А эти корзины уже в свою очередь мапятся к серверам. Количество vbuckets должно всегда оставаться неизменным (изменение количества возможно только при полной очистке данных), но количество серверов можно менять.

Что нам дает vbucket:

  • серверы обслуживают только конкретные vbuckets;
  • как следствие — отсутствие оверхеда на сеть;
  • позволяет масштабироваться вверх и вниз;
  • гарантия консистентности;
  • возможность переноса данных между серверами;
  • репликация.

Звучит хорошо, но как это готовить?
Чтобы получилось утилизировать все преимущества vbucket, приложение должно уметь их использовать, но сейчас практически нет популярных библиотек, которые бы поддерживал vbucket. Здесь на помощь приходит moxi proxy server, который поддерживает все особенности vbucket.

Moxi
Существует много разных прокси-серверов для memcache, но moxi — лидер из тех, кто поддерживает vbucket.

Multithreaded C
Libmemcached
Memcached
Libevent
Protocol conversion

Наиболее популярные продукты, которые поддерживают vbucket: zBase и couchbase.
Ссылки:
http://dustin.sallings.org/2010/06/29/memcached-vbuckets.html
https://github.com/zbase/
https://github.com/couchbase
https://github.com/memcached/memcached/tree/engine-pu


Для Selectel эта встреча — полезный новый опыт: мы впервые пригласили гостей в офис. Спасибо всем, кто пришел — надеемся, было интересно и уютно.

Просьба участникам встречи — напишите, пожалуйста, в комментариях мнение о selectel.meetup: понравилось вам, есть ли замечания, пожелания?

И напоследок — фотографии с первого selectel.meetup.