<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Insight IT</title><link>https://www.insight-it.ru/</link><description></description><atom:link href="https://www.insight-it.ru/tag/solaris/feed/index.xml" rel="self"></atom:link><lastBuildDate>Wed, 13 Jan 2010 20:34:00 +0300</lastBuildDate><item><title>Sun Unified Storage</title><link>https://www.insight-it.ru//storage/2010/sun-unified-storage/</link><description>&lt;p&gt;По работе мне доводилось активно "иметь дело" с железкой от Sun под
названием &lt;a href="https://www.insight-it.ru/goto/683a31cf/" rel="nofollow" target="_blank" title="http://www.sun.com/storage/disk_systems/unified_storage/7410/"&gt;Sun Unified Storage 7410&lt;/a&gt;.
Представляет собой достаточно мощную систему хранения данных с
установленным Solaris, но доступом и управлением исключительно через
веб-интерфейс. Основной "фишкой" системы является модульность: дисковый
массив наращивается подключаемыми внешне дисковыми модулями по примерно
20-50ТБ, сетевой интерфейс также модульный - на выбор начиная от
нескольких обычных Ethernet по 1GBps и заканчивая оптоволокном, CX4 или
InfiniBand. Две таких машины можно легко объединить в одну
виртуальную&amp;nbsp;для повышения надежности доступа к данным, подключив к ним
общий дисковый массив. RAID используется софтверный средствами ZFS,
вполне стандартный набор опций из зеркалирования, stripe, RAID5/6 и их
комбинаций.&lt;/p&gt;
&lt;p&gt;С точки зрения производительности тоже достаточно интересная штука: при
подключении через 4x 1GBps Ethernet (с использованием LACP, но это тема
для отдельного поста) определенно упирается в сеть, но все равно отлично
подходит для использования в решении многих прикладных задач. Из
интересных опций можно отметить прозрачное использование нескольких
SSD-дисков в каждом дисковом массиве в роли кэша.&lt;/p&gt;
&lt;p&gt;Все функции системы абсолютно прозрачны и настраиваются в несколько
кликов через веб-интерфейс, командная строка хоть при желании и
доступна, но практически не нужна. Там же можно увидеть статистику
использования подсистем и прочую полезную информацию. В целом отличная
система хранения данных: простая, надежная, быстрая, удобная,
вместительная и масштабируемая, правда с одним большим НО - цена просто
зашкаливает, прицениться можно, сходив по ссылке в начале записи, но
вообще есть и более дешевые модели в этой серии.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;К чему я это&amp;nbsp;все вспомнил?&lt;/em&gt; На почту пришел очередной рекламный буклет
от Sun с &lt;a href="https://www.insight-it.ru/goto/78e197bb/" rel="nofollow" target="_blank" title="https://dct.sun.com/dct/forms/reg_us_1308_670_0.jsp"&gt;предложением попробовать Sun Unified Storage в виртуальной машине VirtualBox или VMWare&lt;/a&gt;, сам еще не
установил - времени не нашлось, но возможно Вам покажется интересным.
Конечно это не совсем то же самое, что и физическая железка -
производительность дисковых и сетевых подсиситем не померять, но
веб-интерфейс заценить можно.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Wed, 13 Jan 2010 20:34:00 +0300</pubDate><guid>tag:www.insight-it.ru,2010-01-13:storage/2010/sun-unified-storage/</guid><category>7410</category><category>Solaris</category><category>Sun</category><category>Sun Unified Storage</category><category>VirtualBox</category><category>VMWare</category></item><item><title>Архитектура LinkedIn</title><link>https://www.insight-it.ru//highload/2008/arkhitektura-linkedin/</link><description>&lt;p&gt;&lt;a href="https://www.insight-it.ru/goto/801d7bb4/" rel="nofollow" target="_blank" title="https://www.linkedin.com"&gt;LinkedIn&lt;/a&gt; является крупнейшей в мире
социальной сетью для профессионалов. Популярность этого проекта может
быть далека, от более общетематических социальных сетей, таких как,
скажем Facebook, но, тем не менее, нагрузка на серверную часть проекта
создается пользователями серьезная. О том как этот проект с ней
справляется и пойдет речь далее.
&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="predislovie"&gt;Предисловие&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Сообщение о публикации двух презентаций c JavaOne 2008 о LinkedIn и их
&lt;a href="https://www.insight-it.ru/goto/36e64126/" rel="nofollow" target="_blank" title="http://hurvitz.org/blog/2008/06/linkedin-architecture"&gt;обобщении&lt;/a&gt; от
Overn Hurvitz пронеслось по русскоязычным новостным ресурсам уже
достаточно давно, но время черкнуть пару строк обо всем этом нашлось у
меня только сейчас.&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/aef5ee94/" rel="nofollow" target="_blank" title="http://www.slideshare.net/linkedin/linkedins-communication-architecture"&gt;LinkedIn - A Professional Social Network Built with Java&amp;trade; Technologies and Agile Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/515b891c/" rel="nofollow" target="_blank" title="http://www.slideshare.net/linkedin/linked-in-javaone-2008-tech-session-comm"&gt;LinkedIn Communication Architecture&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="statistika"&gt;Статистика&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;22 миллиона пользователей;&lt;/li&gt;
&lt;li&gt;4+ миллиона уникальных посетителей в день;&lt;/li&gt;
&lt;li&gt;40 миллионов просмотров страниц в день;&lt;/li&gt;
&lt;li&gt;2 миллиона поисковых запросов в день;&lt;/li&gt;
&lt;li&gt;ежедневно отправляются 250 тысяч приглашений;&lt;/li&gt;
&lt;li&gt;1 миллион ответов в день;&lt;/li&gt;
&lt;li&gt;2 миллиона электронных сообщений ежедневно.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="platforma"&gt;Платформа&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/tag/solaris/"&gt;Solaris&lt;/a&gt; (как x86, так и SPARC)&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/tomcat/"&gt;Tomcat&lt;/a&gt; и &lt;a href="/tag/jetty/"&gt;Jetty&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/oracle/"&gt;Oracle&lt;/a&gt; и &lt;a href="/tag/mysql/"&gt;MySQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Никакого ORM&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/activemq/"&gt;ActiveMQ&lt;/a&gt; для JMS&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/lucene/"&gt;Lucene&lt;/a&gt; в качестве основы для поиска&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/spring/"&gt;Spring&lt;/a&gt; в роли "клея"&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="servernaia-arkhitektura"&gt;Серверная архитектура&lt;/h3&gt;
&lt;h4&gt;2003-2005&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;одно монолитное веб-приложение;&lt;/li&gt;
&lt;li&gt;одна общая база данных;&lt;/li&gt;
&lt;li&gt;сетевой граф кэшируется в памяти в "Облаке";&lt;/li&gt;
&lt;li&gt;поиск пользователей реализован с помощью &lt;a href="/tag/lucene/"&gt;Lucene&lt;/a&gt;, он
    работал на той же машине, что и "Облако", так как поиск был
    отфильтрован в соответствии с сетью пользователя, таким образом было
    удобно совмещать эти две функции на одной машине;&lt;/li&gt;
&lt;li&gt;веб-приложение напрямую обновляет базу данных, а она, в свою
    очередь, обновляет "Облако".&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2006&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Добавлена репликация для уменьшения нагрузки на основную базу
    данных. Реплики предоставляют данные в режиме "только для чтения", а
    репликация ведется в асинхронном режиме с помощью дополнительного
    компонента под названием Databus, с его появлением обновление данных
    стало выглядеть следующим образом:&lt;ul&gt;
&lt;li&gt;сначала какие-либо изменения происходят в веб-приложении;&lt;/li&gt;
&lt;li&gt;веб-приложение обновляет основную базу данных;&lt;/li&gt;
&lt;li&gt;она, в свою очередь, отправляет обновления на Databus;&lt;/li&gt;
&lt;li&gt;далее уже Databus обновляет: реплики, Облако и поисковый индекс.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Поиск был вынесен на отдельный сервер.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2008&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;веб-приложение само по себе практически ничего не делает: бизнес
    логика распределена по отдельным сервисам;&lt;/li&gt;
&lt;li&gt;веб-приложение все так же предоставляет пользователям графический
    интерфейс, но для его генерации она теперь вызывает сервисы;&lt;/li&gt;
&lt;li&gt;каждый сервис имеет свою специфическую базу данных (т.е.
    вертикальное сегментирование);&lt;/li&gt;
&lt;li&gt;такой подход позволяет другим приложениям (помимо основного)
    получать доступ к LinkedIn, такие приложения были созданы для
    работодателей, рекламных служб, и так далее.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="oblako"&gt;Облако&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;"Облаком" в LinkedIn называют сервер, который кэширует весь граф
    социальной сети в памяти;&lt;/li&gt;
&lt;li&gt;его размеры: 22 миллиона вершин и 120 миллионов ребер;&lt;/li&gt;
&lt;li&gt;занимает 12GB оперативной памяти;&lt;/li&gt;
&lt;li&gt;одновременно держится в памяти в 40 экземплярах;&lt;/li&gt;
&lt;li&gt;построение Облака из данных, в дисковой системе, занимает 8 часов;&lt;/li&gt;
&lt;li&gt;обновления происходят в режиме реального времени с помощью Databus;&lt;/li&gt;
&lt;li&gt;во время остановки данные записываются на диск;&lt;/li&gt;
&lt;li&gt;кэш реализован с помощью C++, а доступ предоставляется по JNI;&lt;/li&gt;
&lt;li&gt;они выбрали именно C++ так как требовалось использовать минимум
    оперативной памяти, а также, задержки, связанные с Garbage
    Collection, были неприемлемыми.&lt;/li&gt;
&lt;li&gt;размещение всех данных в памяти является ограничением, но, как
    удалось выяснить в LinkedIn, разбиение графов на части - не самая
    тривиальная задача.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Облако кэширует целиком весь граф социальной сети LinkedIn, но на
практике же пользователям требуется видеть его со своей точки зрения.
Данная задача является вычислительно сложной, по-этому она выполняется
лишь один раз при создании новой сессии, а затем система поддерживает
результат в кэше. Такой подход требует 2 MB оперативной памяти на
каждого активного пользователя. В течении сессии такой кэш обновляется
только если сам пользователь сделал какие-либо изменения в нем, если же
изменение вызвано другими пользователями - владелец сессии не заметит
изменений.&lt;/p&gt;
&lt;p&gt;Помимо этого используется кэширование профилей пользователей средствами
&lt;a href="/tag/ehcache/"&gt;EHcache&lt;/a&gt;. Одновременно в памяти хранится до 2 миллионов
профилей (из 22 миллионов). Изначально планировалось использовать
алгоритм &lt;abbr title="Least Frequently Used"&gt;LFU&lt;/abbr&gt;, но оказалось,
что иногда &lt;a href="/tag/ehcache/"&gt;EHcache&lt;/a&gt; зависал секунд на 30 во время
перерасчета &lt;abbr title="Least Frequently Used"&gt;LFU&lt;/abbr&gt;, таким
образом было принято решение о использовании вместо него алгоритма
&lt;abbr title="Least Recently Used"&gt;LRU&lt;/abbr&gt;.&lt;/p&gt;
&lt;h3 id="arkhitektura-kommunikatsii"&gt;Архитектура коммуникации&lt;/h3&gt;
&lt;p&gt;Как известно, пользователи практически любой социальной сети генерируют
огромное количество сообщений в единицу времени, причем каждый тип
сообщений обычно требует индивидуального подхода, но в целом их можно
разделить на две категории: постоянные и временные. В LinkedIn
разработчики построили по отдельному сервису, для обработки каждой из
этих категорий. Каждый из них определенно заслуживает отдельного
внимания, так как общего в них мало.&lt;/p&gt;
&lt;h4&gt;Сервис постоянных сообщений&lt;/h4&gt;
&lt;p&gt;Этот коммуникационный сервис выполняет все операции, связанные с
постоянными сообщениями: приватными сообщениями и электронной почтой.
Перед ним ставится вполне тривиальный ряд задач: доставлять сообщения
получателям и сохранять их на постоянной основе, но на самом деле этим
все не ограничивается: должны также поддерживаться, скажем, доставка
сообщений с задержкой, массовые рассылки, отмена отправки сообщения,
возможность добавления в сообщения какого-либо интерактивного контента.
Реализован он был примерно следующим образом:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;вся система работает асинхронно и активно использует JMS;&lt;/li&gt;
&lt;li&gt;клиенты отправляют сообщения так же через JMS;&lt;/li&gt;
&lt;li&gt;далее сообщения перенаправляются с помощью сервиса маршрутизации в
    соответствующий почтовый ящик или напрямую в обработку электронной
    почты;&lt;/li&gt;
&lt;li&gt;доставка сообщений происходит как с помощью Pull (клиенты
    запрашивают свои сообщения), так и с использованием Push (т.е.
    отправки сообщений);&lt;/li&gt;
&lt;li&gt;помимо этого используется &lt;a href="/tag/spring/"&gt;Spring&lt;/a&gt; с их собственными
    закрытыми расширениями, использующими HTTP-RPC.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Приемы, способствующие масштабируемости&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Функциональное сегментирование:&lt;/strong&gt; отправленные, полученные,
    архивные сообщения. &lt;em&gt;(т.е. вертикальное сегментирование)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Классовое сегментирование:&lt;/strong&gt; пользовательские, гостевые,
    корпоративные почтовые ящики.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Сегментирование по диапазонам:&lt;/strong&gt; по идентификаторам пользователей
    или по лексикографическим диапазонам самих сообщений. &lt;em&gt;(т.е.
    горизонтальное сегментирование)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Асинхронное выполнение операций&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Сервис сетевых обновлений&lt;/h4&gt;
&lt;p&gt;Этот сервис обеспечивает работу любых временных уведомлений, например,
вызванных изменением статуса пользователей в контакт-листах. Такие
сообщения должны с течением времени удаляться из-за быстрой потери
актуальности, а также должна поддерживаться группировка и приоритезация
сообщений. Функционирование этого сервиса оказалось не настолько
очевидно, по сравнению с предыдущим, так что до итогового варианта было
перепробовано масса менее удачных решений, но обо всем по порядку.&lt;/p&gt;
&lt;h5&gt;Изначальная архитектура (до 2007 года)&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;используется много серверов, которые могут содержать обновления;&lt;/li&gt;
&lt;li&gt;клиенты отправляют запросы на каждый сервис отдельно: вопросы,
    обновления профилей и т.д.&lt;/li&gt;
&lt;li&gt;на сбор всех данных требовалось относительно много времени.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В 2008 году вся эта система поэтапно эволюционировала собственно в сам
сервис сетевых обновлений:&lt;/p&gt;
&lt;h5&gt;Первая итерация&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;клиент отправляет единственный запрос сервису сетевых обновлений;&lt;/li&gt;
&lt;li&gt;этот сервис в свою очередь параллельно отправляет всем остальным сервисам соответствующие запросы.&lt;/li&gt;
&lt;li&gt;результаты агрегируются и все вместе возвращаются клиенту;&lt;/li&gt;
&lt;li&gt;весь процесс основывается на Pull.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Вторая итерация&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;стал использоваться метод Push: каждый раз, когда происходит
    какое-либо событие, они помещаются в пользовательский "почтовый
    ящик", в момент запроса пользователя ему возвращается просто
    содержимое, уже ожидающее своего звездного часа в специально том
    самом "ящике";&lt;/li&gt;
&lt;li&gt;такой подход сильно ускоряет процесс чтения, так как на тот
    момент данные уже готовы;&lt;/li&gt;
&lt;li&gt;с другой стороны, какая-то часть данных может так никогда и не
    понадобиться, что приводит к бесполезным передвижениям данных и
    лишнему используемому дисковому пространству;&lt;/li&gt;
&lt;li&gt;небольшая часть обработки данных все же производится уже в
    момент запроса пользователя (например, объединение нескольких
    обновлений от определенного пользователя в одно);&lt;/li&gt;
&lt;li&gt;обновления хранятся в &lt;abbr title="Character Large OBject"&gt;CLOB&lt;/abbr&gt;'ах: по одному &lt;abbr title="Character Large OBject"&gt;CLOB&lt;/abbr&gt;'у на каждый тип
    обновления для каждого пользователя (то есть в сумму около 15 &lt;abbr title="Character Large OBject"&gt;CLOB&lt;/abbr&gt;'ов на каждого пользователя);&lt;/li&gt;
&lt;li&gt;сначала использовался размер &lt;abbr title="Character Large OBject"&gt;CLOB&lt;/abbr&gt;'ов равный 8 KB,
    что было явно больше требуемого и приводило к существенному
    количеству неиспользуемого дискового пространства.&lt;/li&gt;
&lt;li&gt;вместо &lt;abbr title="Character Large OBject"&gt;CLOB&lt;/abbr&gt;'ов можно
    было бы использовать дополнительные таблици по одной на каждый
    тип обновлений, но в этом случае пришлось бы постоянно удалять
    из них устаревшие записи, что было бы чрезвычайно неэффективно.&lt;/li&gt;
&lt;li&gt;в дополнение к этому использовался &lt;abbr title="Java Management eXtensions"&gt;JMX&lt;/abbr&gt; для
    мониторинга и изменения конфигурации в реальном времени, что
    оказалось очень удобным и полезным.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Третья итерация&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Цель: повысить производительность путем сокращения количества
    обновлений &lt;abbr title="Character Large OBject"&gt;CLOB&lt;/abbr&gt;'ов,
    так как они требуют много вычислительных ресурсов.&lt;/li&gt;
&lt;li&gt;Был добавлен буфер: колонки в таблицах типа &lt;code&gt;varchar(4000)&lt;/code&gt;, в
    которых данные помещались изначально. При полном заполнении
    ячейки данные перемещаются в &lt;abbr title="Character Large OBject"&gt;CLOB&lt;/abbr&gt;; это позволило
    на порядок сократить количество их обновлений.&lt;/li&gt;
&lt;li&gt;Уменьшен размер самих сообщений об обновлениях.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="i-naposledok-paru-sovetov-ot-linkedin"&gt;И напоследок пару советов от LinkedIn&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;нельзя бесконечно долго ограничиваться одной базой данных:
    используйте много баз данных как с вертикальным, так и с
    горизонтальным сегментированием данных;&lt;/li&gt;
&lt;li&gt;забудьте о ссылочной целостности и кросс-серверных JOIN'ах;&lt;/li&gt;
&lt;li&gt;забудьте о 100% целостности данных;&lt;/li&gt;
&lt;li&gt;при большом масштабе издержки могут стать проблемой: оборудование,
    базы данных, лицензии, системы хранения данных, электроэнергия и так
    далее;&lt;/li&gt;
&lt;li&gt;как только вы станете достаточно крупны и популярны, спаммеры и
    прочие злые люди не заставят себя долго ждать;&lt;/li&gt;
&lt;li&gt;не забывайте про кэширование!!!&lt;/li&gt;
&lt;li&gt;используйте асинхронные потоки данных;&lt;/li&gt;
&lt;li&gt;аналитика и построение отчетов может стать непростой задачей,
    постарайтесь задуматься о них заранее в процессе планирования
    системы;&lt;/li&gt;
&lt;li&gt;имейте всегда ввиду, что Ваша система может упасть в любой момент;&lt;/li&gt;
&lt;li&gt;не стоит недооценивать траекторию своего роста.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ps"&gt;P.S.&lt;/h3&gt;
&lt;p&gt;Когда уже закончил переводить в голову пришла мысль, что если читателям
будет интересно взглянуть на оригинальные презентации (хотябы ради
иллюстрационного материала, который там вполне нагляден), то было бы
проще сделать это прямо здесь, так что вот, для Вашего же удобства:&lt;/p&gt;
&lt;div class="video-container"&gt;&lt;iframe allowfullscreen="" frameborder="0" height="355" marginheight="0" marginwidth="0" scrolling="no" src="//www.slideshare.net/slideshow/embed_code/key/uHbsRNnQFZwThD" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" width="425"&gt; &lt;/iframe&gt;&lt;/div&gt;
&lt;div class="video-container"&gt;&lt;iframe allowfullscreen="" frameborder="0" height="355" marginheight="0" marginwidth="0" scrolling="no" src="//www.slideshare.net/slideshow/embed_code/key/16CML2N96CDeWv" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" width="425"&gt; &lt;/iframe&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Кстати если Вы еще не успели подписаться на &lt;a href="/feed/"&gt;RSS&lt;/a&gt; - сейчас
самое время!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Thu, 11 Sep 2008 04:00:00 +0400</pubDate><guid>tag:www.insight-it.ru,2008-09-11:highload/2008/arkhitektura-linkedin/</guid><category>ActiveMQ</category><category>C++</category><category>EHcache</category><category>Java</category><category>Jetty</category><category>LinkedIn</category><category>Lucene</category><category>MySQL</category><category>Oracle</category><category>Solaris</category><category>Spring</category><category>Tomcat</category><category>архитектура</category><category>архитектура LinkedIn</category><category>Масштабируемость</category></item><item><title>Архитектура Twitter</title><link>https://www.insight-it.ru//highload/2008/arkhitektura-twitter/</link><description>&lt;p&gt;&lt;a href="https://www.insight-it.ru/goto/c2919313/" rel="nofollow" target="_blank" title="https://www.twitter.com"&gt;Twitter&lt;/a&gt; стартовал как побочный подпроект, но
не смотря на это темпы его роста были впечатляющими: путь от 0 до
миллионов просмотров страниц занял всего несколько коротких месяцев.
Ранние решения о проектировании системы неплохо справлялись с небольшими
нагрузками, но они быстро таяли под напором огромного количества
пользователей, желающих разослать весточки всем своим друзьям с ответом
на простой вопрос: а чем ты занимаешься?&lt;/p&gt;
&lt;p&gt;Поначалу все винили &lt;a href="/tag/ror/"&gt;Ruby on Rails&lt;/a&gt; во всех проблемах с
масштабированием, но Blaine Cook, главный архитектор Twitter, встал на
его защиту:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Основной для нас на самом деле является проблема горизонтального
масштабирования, с этой точки зрения &lt;a href="/tag/ror/"&gt;Ruby on Rails&lt;/a&gt; ничем
не хуже других языков программирования или framework'ов: переход на
"более быстрый" язык программирования дал бы нам 10-20% прирост
производительности, в то время архитектурные преобразования, легко
реализованные средствами &lt;a href="/tag/ror/"&gt;Ruby on Rails&lt;/a&gt;, сделали Twitter
быстрее на 10000%.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Даже если &lt;a href="/tag/ror/"&gt;Ruby on Rails&lt;/a&gt; оказался невиновен, как же тогда
Twitter научился с его помощью рости до все больших и больших высот?
&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="istochniki-informatsii"&gt;Источники информации&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Этот текст является продолжением &lt;a href="https://www.insight-it.ru/highload/"&gt;серии переводов&lt;/a&gt;, автор
&lt;a href="https://www.insight-it.ru/goto/9736f7f8/" rel="nofollow" target="_blank" title="http://highscalability.com/scaling-twitter-making-twitter-10000-percent-faster"&gt;оригинала&lt;/a&gt; -
Todd Hoff. На этот раз написать что-либо своими силами у меня не
сложилось, все мысли ушли на другой пост, который я скоро опубликую, а
перевод этот получился несколько менее строгим, чем обычно, но я думаю
ничего страшного.&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/1a76cc37/" rel="nofollow" target="_blank" title="http://video.google.com/videoplay?docid=-7846959339830379167"&gt;Scaling Twitter Video&lt;/a&gt;
    от Blaine Cook.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/a004222e/" rel="nofollow" target="_blank" title="http://www.slideshare.net/Blaine/scaling-twitter"&gt;Scaling Twitter Slides&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/7541c4c6/" rel="nofollow" target="_blank" title="http://talklikeaduck.denhaven2.com/articles/2007/06/22/good-news"&gt;Good News&lt;/a&gt;
    блог пост от Rick Denatale&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/96735c2c/" rel="nofollow" target="_blank" title="http://pragmati.st/2007/5/20/scaling-twitter"&gt;Scaling Twitter&lt;/a&gt; блог
    пост от Patrick Joyce&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/7267856d/" rel="nofollow" target="_blank" title="http://readwritetalk.com/2007/09/05/biz-stone-co-founder-twitter/"&gt;Twitter API Traffic is 10x Twitter&amp;rsquo;s Site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/5eb63819/" rel="nofollow" target="_blank" title="http://www.slideshare.net/britt/a-small-talk-on-getting-big-113066"&gt;A Small Talk on Getting Big. Scaling a Rails App &amp;amp; all that Jazz&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="platforma"&gt;Платформа&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/tag/ruby-on-rails/"&gt;Ruby on Rails&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/erlang/"&gt;Erlang&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/mysql/"&gt;MySQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/mongrel/"&gt;Mongrel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/munin/"&gt;Munin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/nagios/"&gt;Nagios&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/google-analytics/"&gt;Google Analytics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/awstats/"&gt;AWStats&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/memcached/"&gt;Memcached&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="statistika"&gt;Статистика&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Более 350000 пользователей. Точная цифра, как обычно, держится в
    секрете.&lt;/li&gt;
&lt;li&gt;Около 600 запросов в секунду.&lt;/li&gt;
&lt;li&gt;В среднем система поддерживает 200-300 соединений в секунду.
    Максимум обычно достигается при значении 800.&lt;/li&gt;
&lt;li&gt;MySQL обрабатывает примерно 2400 запросов в секунду.&lt;/li&gt;
&lt;li&gt;180 экземпляров приложений на Rails, использующих Mongrel как
    веб-сервер.&lt;/li&gt;
&lt;li&gt;1 MySQL сервер (одна большая машина с 8 ядрами) и 1 slave,
    используемый лишь для статистики и отчетов.&lt;/li&gt;
&lt;li&gt;30+ процессов для выполнения произвольных работ.&lt;/li&gt;
&lt;li&gt;8 Sun X4100&lt;/li&gt;
&lt;li&gt;Обработка запроса обычно занимает у Rails 200 миллисекунд.&lt;/li&gt;
&lt;li&gt;В среднем ответ на запрос к базе данных занимает 50-100 миллисекунд.&lt;/li&gt;
&lt;li&gt;Более 16 GB выделено под &lt;a href="/tag/memcached/"&gt;memcached&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="arkhitektura"&gt;Архитектура&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Проект столкнулся с массой проблем, связанных с масштабируемостью.
    Маленькая птичка частенько давала сбои.&lt;/li&gt;
&lt;li&gt;Изначально не было реализовано никаких форм мониторинга, графиков
    или статистики, это очень затрудняло обнаружение м решение
    возникающих проблем. Впоследствии были внедрены &lt;a href="/tag/munin/"&gt;Munin&lt;/a&gt;
    и &lt;a href="/tag/nagios/"&gt;Nagios&lt;/a&gt;. Разработчики столкнулись с некоторыми
    трудностями при использовании этих продуктов в
    &lt;a href="/tag/solaris/"&gt;Solaris&lt;/a&gt;. Помимо этого был использован сервис Google
    Analytics, но от него обычно мало толку, особенно когда страницы
    даже не загружаются.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Активное использование кэширования средствами &lt;a href="/tag/memcached/"&gt;memcached&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Например, если подсчет количества чего-либо выполняется медленно,
намного эффективнее один раз запомнить результат в
&lt;a href="/tag/memcached/"&gt;memcached&lt;/a&gt;, чем каждый раз считать его заново.&lt;/li&gt;
&lt;li&gt;Получение информации о статусе своих друзей - непростая задача.
Вместо использования запросов информация о статусе друзей
обновляется в кэше. База данных совсем не используется. Такой подход
позволяет получить предсказуемое время отклика (ограниченное сверху примерно 20 миллисекундами).&lt;/li&gt;
&lt;li&gt;Объекты ActiveRecord настолько велики, что кэширование их
нецелесообразно. Критичные атрибуты хранятся в хэше, а остальная их часть подвергается "ленивой загрузке" в момент запроса на доступ.&lt;/li&gt;
&lt;li&gt;90% запросов являются запросами к API. Таким образом кэширование
страниц или их фрагментов становится бессмысленным, зато никто не мешает им кэшировать сами API запросы.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Внутренняя организация работы с сообщениями:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Сообщения очень активно используются: производители генерируют
сообщения, они образуются в очереди, а затем распространяются по
потребителем.&lt;/li&gt;
&lt;li&gt;Основная функция Twitter заключается в реализации
своеобразного моста между различными форматами электронных сообщений
(SMS, электронная почта, сервисы мгновенного обмена сообщениями и так далее).&lt;/li&gt;
&lt;li&gt;Чтобы инвалидировать в кэше информацию можно просто отправить внутреннее сообщение, зачем выполнять все действия синхронно?&lt;/li&gt;
&lt;li&gt;Изначально этот механизм основывался на DRb (distributed Ruby) -
библиотека, позволяющая отправлять и принимать сообщения сообщения
между удаленными Ruby-объектами по TCP/IP. Но она была несколько
странноватой, да и являлось потенциально слабым местом с точки зрения стабильности.&lt;/li&gt;
&lt;li&gt;Со временем сервис перевели на Rinda, представляющую собой набор
общих для всей системы очередей. Но и у нее были недостатки: все очереди были постоянными, а данные терялись при сбоях.&lt;/li&gt;
&lt;li&gt;Следующей попыткой был Erlang. Но однажды возникла проблема: каким
образом сломавшийся сервер может продолжать работать, но при этом в
очереди откуда-то возникли целых 20000 ожидающих пользователей? Разработчики не знали. На лицо явный недостаток документации...&lt;/li&gt;
&lt;li&gt;В конце концов решение было разработано своими силами: Twitter
выпустил &lt;a href="/tag/starling/"&gt;Starling&lt;/a&gt;, распределенный легковесный
сервер очередей, написанный на Ruby и поддерживающий протокол memcache. Сейчас серверная часть Twitter управляется именно им.&lt;/li&gt;
&lt;li&gt;Распределенные очереди позволяют переживать сбои путем записи их
на диск в критических ситуациях. Другие крупные интернет-проекты также часто пользуются таким подходом.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Работа с SMS осуществляется с помощью сторонних сервисов и
    предоставляемых ими шлюзов. Достаточно дорогое удовольствие.&lt;/li&gt;
&lt;li&gt;Развертывание:&lt;ul&gt;
&lt;li&gt;Просто запускаются дополнительные сервера с mongrel, более элегантного решения пока нет.&lt;/li&gt;
&lt;li&gt;Все внутренние ошибки выдаются пользователям, если обслуживающий
их mongrel сервер на данный момент заменяется.&lt;/li&gt;
&lt;li&gt;Все сервера останавливаются одновременно. Отключение их по одному
по определенным причинам не используется.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Неправильное использование сервиса:&lt;ul&gt;
&lt;li&gt;Много времени сервис был не доступен, так как люди проходились
специальными программами по сайту с целью добавить всех кто
попадался под руку в друзья. 9000 друзей за 24 часа. Это
просто-напросто останавливало работу сайта.&lt;/li&gt;
&lt;li&gt;Были разработаны средства для своевременного обнаружения таких
ситуаций.&lt;/li&gt;
&lt;li&gt;Будте беспощадными, таких пользователей нужно просто удалять.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Сегментирование:&lt;ul&gt;
&lt;li&gt;Пока оно только в планах, сейчас оно не используется.&lt;/li&gt;
&lt;li&gt;В будущем оно будет основываться на времени, а не на
пользователях, так как запросы обычно очень локальны по времени.&lt;/li&gt;
&lt;li&gt;Сегментирование будет не так просто реализовать благодаря
автоматическому запоминанию результатов выполнения функций для
последующего повторного их использования. Никто не даст гарантии,
что операции "только для чтения" на самом деле будут таковыми
являться. Запись в slave, работающий в режиме read-only, - не самая
лучшая идея.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;API Twitter генерирует в 10 раз больше трафика, чем сам сайт.&lt;ul&gt;
&lt;li&gt;Их API - самая важная вещь из всех, что они разработали.&lt;/li&gt;
&lt;li&gt;Простота сервиса позволила разработчикам строить свои приложения
поверх инфраструктуры Twitter, привнося все новые и новые идеи.
Например, Twitterrific - красивый способ использовать Twitter в
небольшой команде.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Мониторинг используется для остановки слишком больших процессов.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="podvodim-itogi"&gt;Подводим итоги&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Общайтесь со своим сообществом. Не прячьтесь и не пытайтесь решить
    абсолютно все проблемы самостоятельно. Много отличных людей будут
    готовы помочь, достаточно лишь попросить.&lt;/li&gt;
&lt;li&gt;Рассматривайте вашу стратегию масштабирования как бизнес-план.
    Соберите советы помощников для того чтобы облегчить для себя
    принятие решений.&lt;/li&gt;
&lt;li&gt;Стройте свой проект сами. Twitter потратил много времени, пытаясь
    приспособить готовые решения других людей, которые казалось бы
    должны работать, но это оказалось не совсем так. Лучше построить
    какие-то вещи самостоятельно, чтобы иметь высокую степень контроля
    над ситуацией и иметь возможность привносить новые возможности как
    только они понадобились.&lt;/li&gt;
&lt;li&gt;Ставьте перед своими пользователями разумные ограничения. На обычных
    пользователей это не повлияет, но когда кому-нибудь взбредет в
    голову попытаться сломать систему (а такой человек рано или поздно
    найдется) - они сыграют свою роль и спасут работоспособность
    системы.&lt;/li&gt;
&lt;li&gt;Не делайте базу данных центральным узким местом системы, врядли Ваше
    приложение на самом деле требует гигантских операций по объединению
    данных из нескольких таблиц. Используйте кэширование, или проявите
    свою смекалку для поиска альтернативных способов достижения того же
    результата.&lt;/li&gt;
&lt;li&gt;Предусмотрите возможность сегментирования с самого начала, тогда
    перед Вами всегда будут открыты пути для дальнейшего
    масштабирования.&lt;/li&gt;
&lt;li&gt;Очень важно вовремя осознать, что сайт начинает работать медленно.
    Сразу стоит задуматься о системе отчетов для отслеживания
    потенциальных проблем.&lt;/li&gt;
&lt;li&gt;Оптимизируйте базу данных:&lt;ul&gt;
&lt;li&gt;Индексируйте все таблицы, Rails не будет делать это за Вас.&lt;/li&gt;
&lt;li&gt;Используйте "explain" для анализа выполнения запросов. Результаты
могут не совпадать с Вашими ожиданиями.&lt;/li&gt;
&lt;li&gt;Денормализуйте данные. Один только этот совет порой может спасти
ситуацию. Для примера, в Twitter хранят все ID друзей каждого
пользователя вместе, это позволило избежать многих ресурсоемких
запросов.&lt;/li&gt;
&lt;li&gt;Избегайте комплексного объединения данных из нескольких таблиц.&lt;/li&gt;
&lt;li&gt;Избегайте сканирования больших наборов данных.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Кэшируйте все, что только можно.&lt;/li&gt;
&lt;li&gt;Тестируйте все максимально тщательно:&lt;ul&gt;
&lt;li&gt;Когда Вы развертываете приложение, Вы должно быть уверены, что оно
будет работать корректно.&lt;/li&gt;
&lt;li&gt;Они используют полный набор средств для тестирования. Таким
образом, когда произошла неполадка в кэшировании, они узнали о ней
еще до того как она на самом деле произошла.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Длительно функционирующие процессы стоит оформить в виде daemon'ов.&lt;/li&gt;
&lt;li&gt;Используйте уведомления об исключительных ситуациях в совокупности с
    ведением логов, это необходимо для своевременного реагирования на
    них.&lt;/li&gt;
&lt;li&gt;Не делайте глупостей!&lt;ul&gt;
&lt;li&gt;Масштаб проект несколько меняет понятие "глупость".&lt;/li&gt;
&lt;li&gt;Пытаться загрузить 3000 друзей в память одновременно может
заставить сервер временно перестать функционировать, хотя когда
друзей было всего 4 - этот механизм прекрасно работал.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Большая часть производительности зависит не от использованного языка
    программирования, а от продуманной структуры приложения.&lt;/li&gt;
&lt;li&gt;Превратите свой сайт в открытый сервис с помощью создания API. Их
    API является ключом к успеху Twitter. Он позволяет пользователям
    создавать постоянно расширяющуюся экосистему вокруг Twitter,
    соревноваться с которой не так-то просто. Вы никогда не сможете
    сделать столько же работы, сколько смогут Ваши пользователи для Вас,
    Вам просто не хватит креативных идей. Так что не стесняйтесь,
    откройте свое приложение и сделайте интеграцию Вашего приложения с
    другими максимально простой и удобной!&lt;/li&gt;
&lt;/ul&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Sat, 10 May 2008 12:36:00 +0400</pubDate><guid>tag:www.insight-it.ru,2008-05-10:highload/2008/arkhitektura-twitter/</guid><category>AWStats</category><category>Erlang</category><category>Google Analytics</category><category>Memcached</category><category>mongrel</category><category>Munin</category><category>MySQL</category><category>Nagios</category><category>Ruby on Rails</category><category>Solaris</category><category>Starling</category><category>Twitter</category><category>архитектура</category><category>архитектура Twitter</category></item></channel></rss>