Наверх ▲

Масштабируемая система голосования на базе PostgreSQL (PgQ)

Сергей Нековаль Сергей Нековаль Сергей Нековаль, главный архитектор компании Грамант.

Сергей Нековаль: Добрый день! Меня зовут Сергей Нековаль, я работаю системным архитектором в компании «Грамант». Если я вижу программное обеспечение, которое может облегчить мою жизнь, я у удовольствием его использую.

В данном случае речь пойдет о пакете Skytools и интерфейсе программирования приложений PgQ в составе пакета.

Доклад будет построен следующим образом. Сначала я кратко расскажу о системе. Потом - о PgQ и том, как мы его используем. И, наконец, о хороших и плохих вещах, которые могут иметь место при использовании PgQ.

Где происходит голосование, о котором упомянуто в названии презентации? На самом японском видеопортале: пользователи голосуют за или против той или иной записи. Кроме того, они могут оставлять комментарии, добавлять материалы в избранное или только просматривать их.

Соответственно, речь идет о подсчете тех операций, которые может совершить пользователь. Кнопки голосования работают не так, как можно предположить. Красная кнопка - это голос «за», синяя – «против», оранжевая – "оставить комментарий". Рядом с ними располагаются счетчики.

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

В системе также действует отличная система рейтингов. На главной странице их показывается около десятка. Рейтинг – это список видеозаписей, опубликованных в опреденном порядке по некоторому принципу. Рейтинговая формула основана на статистических данных: числе просмотров, голосов (положительных и отрицательных), комментариев.

Помимо записи голосов в хранилище, необходимо осуществлять их показ, подсчет и ведение истории для видения динамики происхощего. В нашем случае подсчет ведется по дням. Подобная статистика очень интересна.

В системе происходит 3 основных вида событий: просмотры, голоса, избранное. Можно спросить: "При чем тут голосование?"

Конечно, трафик просмотров гораздо больше. Наша основная забота – отработка всех событий показа видео. Голосов не так много, поэтому голосование волнует нас в меньшей степени.

Как выглядит наша система? Это система, которая подсчитывает все события, связанные с видео и набором рейтингов, которые мы получаем на выходе.

Что мы имеем в системе на 2008 год (старый вариант системы)? Во-первых, использование файлов для суммирование голосов. Во-вторых, пересчет рейтинга с определенным интервалом времени. Это означает, что вы не можете произвольно менять этот параметр в зависимости от загрузки системы. Это может быть достаточно неудобно, особенно при высокой нагрузке. Подсчет – весьма требовательное к ресурсам занятие.

В третьих, если база данных перегружена, статистика начинает сильно запаздывать. А количество зарегистрированных пользователей достигает 150-200 тысяч.

Существует и другой вариант системы, который мы называем «китайским» (им занимались и китайские специалисты). Он предполагает исторические таблицы, где содержится ежедневная динамика всех событий, и таблицу голосов, где хранится число всех событий, имеющих отношение к каждому видеоролику.  Имеется Front end, PHP, база данных.

Что мы хотим c этим делать? Мы хотим, чтобы система, в конце концов, работала. Необходимо произвести разгрузку базы и использовать ее для других целей. Кроме того, требуется ускорить подсчет рейтингов.

Какое мы предлагаем решение? Предлагается организовать события в очередь и использовать некоторое API-направление этой очереди. Логику обработки для очереди формировать удобно. События будут двигаться по цепочке в строгой последовательности. Они могут подвергаться обработке (не один раз) и агрегации.

Для выполнения наших задач имеется пакет Skytools, который разработан компанией Skype. Это открытое программное обеспечение. Skytools содержит, помимо всего прочего, систему асинхронной репликации Londiste. Она базируется на системе обработки очередей PGQ.

Также в Skytools есть другие полезные вещи, которых я сейчас касаться не буду. Текущая версия имеет номер 2.1.11 или 2.3.10. На подходе - Skytools 3.

Чего мы ждем от работы с PgQ? Во-первых, удобного интерфейса программирования приложений (англ. API). Во-вторых, обеспечения сохранности данных. Если кто-то проголосовал, мы должны быть уверены, что голос действительно учтен.

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

PgQ хранит данные, в свою очередь, в базе данных Postgres, в таблицах событий. Эти таблицы специально организованы таким образом, чтобы запись была максимально облегчена, поскольку запись события – наиболее часто повторяющаяся операция.

Событие позволяет PgQ передавать свои данные в текстовом виде. В PgQ нам интересно не событие само по себе, а партии событий.

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

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

Как устроен PgQ? Существует так называемый ticker – управляющий процесс. Любое число "производителей" (англ. producer) – это определенные программы, которые расставляют события в очередь (англ. queue). Для этого в простейшем случае они используют хранимые внутри Postgres опции. Очереди хранятся в базе (таблицах).

К этим очередям нужно подключить определенное число "потребителей" (англ. consumer). К одной очереди можно подключить несколько кусочков кода. PgQ гарантирует, что событие будет доставлено каждому "потребителю".

Допустим,  вы хотите отправить e-mail в связи с каким-либо событием и одновременно отправить некий HTTP-запрос с уведомлением. Вы можете создать двух "потребителей", и они оба получат нужное событие. Один из них может обработать его не сейчас, а позже. В этом случае событие будет считаться обработанным одним "потребителем", но второй получит напоминание о повторе, о чём я расскажу позже более подробно.

Очереди никак не связаны между собой. Вы можете создать в системе сколько угодно независимых очередей и подключать к ним "потребителей".

Ticker – программа, написанная на Python. Это управляющий процесс, который отвечает за обработку очередей.

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

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

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

Здесь уместно упомянуть о повторной попытке (англ. retry), при которой событие остается в очереди, но будет обработано позже в соответствии с ее настройками. Существует prime-период, после которого оно снова попадет к "потребителю".

Что еще работает в системе, кроме Ticker? "Потребитель" (англ. consumer) – это некий процесс, написанный либо на языке Python, либо на PHP, либо на Java, либо на SQL. Для всех четырех языков есть свой интерфейс программирования приложений. Он достаточно прост, но, на мой взгляд, для Python создана наиболее функциональная версия.

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

Все это обернуто в набор библиотек Python, который прячет от вас большинство деталей.

Фактически вам нужно создать только один метод для обработки партий. Все будет работать строго последовательно.

"Производителем" (англ. producer) может быть программа на любом языке, который может обработать определенный sql. Это простейший вызов функции для вставки события в очередь.

Более сложные "производители" действуют по-другому.

Чем нам настолько нравится в PgQ, что мы решили его использовать в нашей системе?

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

Но иногда вы создаете событие и хотите, чтобы на это событие была какая-либо реакция. Допустим, вам добавили строчку в базу данных и вы хотите отправить электронное письмо. Cобытие создается той же транзакцией. Т.е. если вдруг случится откат транзакции, событие тоже откатится.

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

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

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

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

PgQ позволяет вам получать все основные параметры очереди непосредственно из базы, вследствие чего осуществлять мониторинг довольно просто.

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

Создаем следующий вариант. Мы видим, что таблицы, в целом остались неизменными. Исторические таблицы по-прежнему существуют. Мы оставляем таблицы голосов: эти данные нужны базе и аналитикам. Естественно, требуются данные о текущем состоянии, голосовании и счетчик показа для всех видео.

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

Очередь PgQ хранится в базе. Front end, написанный на PHP, осуществляет доставку событий. Это может быть голосование, показ, комментарий. Соответственно, событие записывается в очередь.

Также используется memcached - исключительно в целях кэширования статистики.

Что изменилось в новой схеме? Структура базы данных осталась прежней. "Производителем" является front end.  Добавляется memcache, где хранится статистика и данные рейтингов.

Что происходит с очередями?

Существует большая очередь под названием "счетчик" (англ. counter), где содержатся все события системы. Поток событий довольно большой. Они суммируются специальным "потребителем" event_count. Этот же "потребитель" отвечает за обновление исторических таблиц, текущей статистики, данных в memcached.

В memcached отсылаются все обновления, которые накопились в "потребителе" после обработки партии событий. Если по пути возникают проблемы, "потребитель" реагирует по-разному. На какие-то события он может сказать "попытаться снова". Некоторые события он распознает как “провалено”. Но "провалено" – ситуация редкая, т.к. чаще удобнее сказать, что событие завершилось успешно, чтобы очередь двигалась дальше.

Очередь "рейтинг" (англ. rating) тоже присутствует. Там хранятся события, которые уведомляют о том, что нужно пересчитать рейтинги. Это должно происходить не каждый раз, а в случае какого-либо изменения.

Что может измениться? Статистика (число просмотров, голосов и так далее). Это влияет на формулу расчета рейтинга. Может измениться сам состав видео. Допустим, пользователь был забанен. Некоторая инфомрация, связанная с ним, исчезнет. Соответственным образом должны измениться и рейтинги. Какое-либо видео также может быть удалено.

Существует еще один "потребитель", который обрабатывает рейтинги, но ничего не суммирует. Единственное значение этой очереди заключается в том, чтобы не считать рейтинг. Мы накопили несколько запросов на накопление рейтинга. Это дорогостоящая процедура, мы не хотим бессмысленно запускать ее. Происходит удаление дубликатов. Предоставляется гарантия, что рейтинг подсчитывается единожды. Далее рейтинги поступают в memcache.

Расскажем подробнее о регулирование очередей. У нас разные очереди, и в них поступает разное число событий. Как PgQ позволяет управлять очередью?

Существует два основных параметра. Во-первых, max_lag, который определяет время. Во-вторых, max_count (некое число). Max_count определяет максимальный размер партии событий. Как только в очереди образуется max_count событий, ticker (процесс, осуществляет контроль) выделяет новую партию.

Max_lag – это ограничение по времени. В чем смысл? Не всегда система загружена. Тем не менее, вы хотите, чтобы обновления происходили, даже если у вас не накопилось max_count событий в очереди. Вы хотите запустить "потребителя". Если допустимое время истечет (max_lag), будет сгенерирована очередная пустая партия. Либо, если там и будет событие, то партия окажется невелика. Тем не менее, все события пройдут по цепочке и вызовут обновления. Max_lag, скорее всего, сработает в условиях недостаточной загруженности системы, а max_count – в условиях пикового режима, когда в систему поступает максимум данных.

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

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

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

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

После приведенной аналогии посмотрим, как регулируется продакшн-система. У нас есть, грубо говоря, две "трубы". Это основная очередь событий (до 10 миллионов в сутки) и очередь рейтингов (она поменьше и не так нам интересна).

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

Чтобы база данных оказалась загружена не до конца и имела некий запас, надо увеличивать lag и стремиться к тому, чтобы происходила агрегация максимального числа событий. Чем лучше мы справимсяс данной задачей, тем меньше записей окажется в исторических таблицах, которые довольно "тяжелые". 150 тысяч – таков размер партии, который обеспечивает агрегацию порядка 1 к 10 или 1 к 15. Грубо говоря, на 150 тысяч событий у вас будет 10-15 тысяч записей и 10-15 тысяч обновлений исторических таблиц.

В очереди "рейтинг" lag достаточно маленький. Не так важно, каков он. Более значимую роль играет max_count.

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

Перейдём к вопросу о производительности самой базы. Можем ли мы сделать с ней нечто такое, чтобы ускорить процесс? Стоит упомянуть про Vacuum для Postgres. У нас - MVCC база, без Vacuum нельзя обойтись никак. При правильной настройке Vacuum все остальное пойдет гораздо легче.

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

Также нельзя забывать о модернизации оборудования. Для решения некоторых проблем достаточным оказывается покупка SSD-диска. 

Выключение fsync необязательно производить во всех базах. Речь идет только о той базе, которая содержит очереди событий, поскольку события – это всегда массивная запись. Fsync увеличивает пропускную способность канала с точки зрения записи.

Какие негативные ситуации могут иметь место при выключенном fsync? При сбое в операционной системе транзакции могут исчезность.

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

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

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

Асинхронность - и плюс, и минус PgQ. Плюс: мы видим, что можно выровнять загрузку системы. За счет регулировки, осуществляемой Ticker возможно обеспечение фиксированного обмена партий событий, регулирование скорости обработки.

С другой стороны, плохо, что операции происходят асинхронно. После голосования рейтинги не обновляются немедленно. Какое время должно пройти - зависит от построения системы.

При наличии производительного оборудования задержка может оказаться очень небольшой. Пользователь может её практически не заметить.

В данном случае уместно пойти на определенные хитрости. Допустим, на странице пользователя увеличился счетчик голосов и счетчик показов. На самом деле, эти данные еще не попали в базу: они временны. Т.е. влияния на рейтинги оказано еще не было.

Если пользователи готовы к подобному и вы в состоянии правильно объяснить ситуацию с задержкой в изменении рейтинга, тогда всё в порядке. Через некоторое время пользователь увидит актуальные данные. Насколько принципиально увидеть их сразу - вопрос компромисса.

В названии доклада было упомянуто масштабирование. Что можно с ним сделать? У нас система с одной центральной базой данных, где хранится вся информация. При десяти миллионах событий система со своей задачей справляется хорошо. Как возможно ее масштабировать, например, на 100 миллионов событий?

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

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

Если дела совсем плохи (допустим, исправляется именно запись в очереди), придется производить разделение на несколько плаз. Потребуется создать несколько одинаковых очередей в разных базах данных. Данную операцию нельзя назвать шардингом в строгом смысле этого слова: данные из одинаковых очередей будут собраны в одну базу. Но процесс будет происходить асинхронно. Это не является узким местом системы. Соответственно, разные Front end будут создавать разные базы. Или, может быть, стоит изменить балансировку.

Я сейчас рассуждаю не про наш случай, а чисто гипотетически.

Skytools 3 предлагает Cooperative Consumers, что может весьма облегчить нам жизнь. Благодаря этой разработке, на одной очереди может работать один и тот же программный код "потребителей" и получать поочередно или по мере освобождения партии из одной и той же очереди.

В Skytools 2 обработка происходить строго последовательно. "Потребитель" запросил партию, обработал его, запросил следующий, обработал. На очереди - много событий. Было бы хорошо применить параллельную обработку партий.

Как может выполняться подобная операция? В Skytools 2 – никак. В Skytools 3 можно инициировать дополнительный процесс. Но необходимо следить за тем, насколько эффективно выполняется параллельная работа "потребителей". Может быть, у них есть узкое место, на которое стоит обратить внимание?

Допустим, у вас не 100 миллионов, а миллиард событий. На самом деле, вы счастливец. У вас очень много пользователей. Судя по всему, вы работаете в Facebook или в Google.

В таком случае, скорее всего, без суммирования на Front-end не обойтись. Этот вариант - крайний.

Вышеупомянутую операцию можно осуществить с разной степенью надежности. Вариантов достаточно много: от Key-Value storage до суммирования в памяти.

Каковы недостатки PgQ? Во-первых, длину очереди узнать нельзя.

Во-вторых, нельзя очистить очередь. Единственный способ это сделать – создать пустого "потребителя", который достанет все события. Можно также попробовать выполнить удаление через таблицу.

Текстовый формат событий - достаточно универсальный, но лично мне он не нравится. События содержат в URL-коде определенные данные. В системе репликаций используется Londiste.

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

Википедия содержит гораздо больше информации на этот счет.

В принципе, тут есть бонусный слайд.

Вопросы:

Вопрос из зала:
Большое спасибо за антирекламу Postgres. Несколько вопросов. Сколько рабочего времени заняло написание всего этого?
Сергей Нековаль:
Неделю.
Вопрос из зала:
Почему использовался PostgreSQL, а не стандартный ActiveMQ, RabbitMQ?
Сергей Нековаль:
Если у вас есть Postgres и вы хотите иметь дело с группами событий, то это достаточно удобно. Если вам не нужны группы и вы хотите использовать face commit или еще что-то сложное, то PgQ для этого не очень подойдет.
Вопрос из зала:
Сколько таблиц требуется для одного события?
Сергей Нековаль:
Штук 10, по-моему. 
Вопрос из зала:
Вы можете вернуться к графику списка?

Вопрос из зала:
Мне кажется, вы либо нас, либо себя обманываете. 10 килобайт, 3 килобайта в секунду среднее арифметическое – это не highload. База не загружена. У вас нагрузка, о которой вы говорили, порядка тысячи событий в секунду. Не сходится.
Сергей Нековаль:
Это все правда. 10 миллионов событий в сутки.
Вопрос из зала:
Получается, у вас 3 байта на событие.
Сергей Нековаль:
За счет агрегации – да.
Вопрос из зала:
Очередь тоже хранится?
Сергей Нековаль:
Сама очередь хранится в базе. Но привыкли, что в fsync хранение очереди переходит, по большому счету, в память. Fsync делает все это гораздо эффективнее.
Вопрос из зала:
Если вы хотите, чтобы пользователи сразу видели актуальный счетчик, почему бы сразу не сделать атомарный инкремент memcache?
Сергей Нековаль:
Такой вариант тоже есть. Понятно, что это тоже небольшой обман, но немного лучший, чем обыкновенная инкрементация страниц.
Вопрос из зала:
Вы пробовали использовать другие системы очередей, кроме PgQ?
Сергей Нековаль:
В этой системе – нет.
Вопрос из зала:
Почему был выбран PgQ?
Сергей Нековаль:
Я считаю, что для Postgres это самое логичное решение.
Вопрос из зала:
Насколько я понимаю, PgQ удобно использовать из-за процедур хранения?
Сергей Нековаль:
Да, эта процедура и есть часть PgQ.
Вопрос из зала:
Я понимаю. Но в противном случае оверхед Postgres с каждой очереди гораздо выше, чем в какой-нибудь другой системе.
Сергей Нековаль:
Какая-то другая очередь где хранится? Если она хранится в Postgres, разницы не будет.
Вопрос из зала:
Понятно. Но есть более эффективные системы?
Сергей Нековаль:
Эффективные в каком плане? Они обеспечивают надежность, хранение?
Вопрос из зала:
Да-да. Обеспечивают надежность.
Сергей Нековаль:
Тогда это то же самое, вид сбоку. Это база с записью на диск.
Вопрос из зала:
Вы сказали, что у вас разбор очереди PgQ некоторым образом связан с нагрузкой на сервер в данный момент времени. Можно подробнее: как это учитывается?
Сергей Нековаль:
Проблема решается подборкой параметров max_count и max_lag.
Вопрос из зала:
Этим значением вы осуществляете требуемый контроль?
Сергей Нековаль:
Да. Вы можете видеть, насколько отстает "потребитель" (англ. consumer). PgQ выдает данные с помощью своей функции. Когда вы видите, что "потребитель" не справляется со своими задачами, надо что-то предпринимать. Но по графику Dick I/O видно, что пока он хорошо работает.
Вопрос из зала:
Насколько велика ваша пользовательская база?
Сергей Нековаль:
Имеется в виду, какая по объему? 50% базы влезает в память. Насколько я помню, там SSD-диски и 32 мегабайта памяти. Сама база, по-моему, гигабайт 100, если учитывать индексы. Большая часть влезает в память.
Вопрос из зала:
У вас нет админа?
Сергей Нековаль:
Человека, который за это отвечает, сейчас на конференции нет. Если у вас есть к нему вопрос, я могу передать.

Комментарии

0
# 6 апреля 2016 12:38
видос про обезьяну с гранатой http://profyclub.ru/docs/145

Только пользователи могут оставлять комментарии

Возможно, вам будет интересно:

Денис Бесков

Денис Бесков

Тренер, консультант, организатор "With a Little Help from My Friends".

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

Сергей Архипенков

Сергей Архипенков

PMP PMI, эксперт в управлении разработкой ПО, вице-президент Гильдии менеджеров программных проектов.

Я попытаюсь представить свою картину мира о том, какими навыками должен обладать лидер, что он должен делать, чтобы сплотить вокруг себя эффективную команду.

Евгения Фирсова

Евгения Фирсова

Руководитель отдела веб-интерфейсов, Яндекс.Деньги.

Я хочу рассказать или, если угодно, определиться и пожаловаться вслух (мне приятно жаловаться вслух) о том, как работать, когда работать некому.