Простыми словами про руководящие принципы и стек технологий

Instagram увеличил количество пользователей с 0 до 14 миллионов всего за год, с октября 2010 по декабрь 2011 года. Они сделали это всего с тремя инженерами.

Они сделали это, следуя 3 ключевым принципам и имея надежный технологический стек.

  • Делайте все очень просто

  • Не изобретайте велосипед заново

  • По возможности используйте проверенные и надежные технологии

Стек

Ранняя инфраструктура Instagram работала на AWS, используя EC2 с Ubuntu Linux. Для справки: EC2 — сервис Amazon, который позволяет разработчикам арендовать виртуальные компьютеры.

Чтобы упростить задачу и поскольку мне нравится думать о пользователе с точки зрения инженера, давайте рассмотрим жизнь пользовательского сеанса. (Пометим это, как «Сеанс»)

Клиент

Сеанс: Пользователь открывает Instagram

Изначально Instagram был запущен как приложение для iOS (прим. пер.: клиент) в 2010 году. Поскольку Swift был выпущен в 2014 году, мы можем предположить, что Instagram был написан с использованием Objective-C и комбинации других вещей, таких как UIKit.

Балансировка нагрузки

Сеанс: После открытия приложения запрос на получение фотографий основного канала отправляется на серверную часть, где он попадает в балансировщик нагрузки Instagram.

Instagram использовал Elastic Load Balancer от Amazon. У них было 3 экземпляра NGINX, которые менялись местами в зависимости от их работоспособности.

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

Сервер

Сеанс: Балансировщик нагрузки отправляет запрос на сервер приложений, который содержит логику для правильной обработки запроса.

Сервер приложений Instagram использовал Django и был написан на Python, а Gunicorn был сервером WSGI.

В качестве напоминания: WSGI (интерфейс шлюза веб-сервера) перенаправляет запросы от веб-сервера к веб-приложению.

Instagram использует Fabric для параллельного запуска команд во многих экземплярах одновременно. Это позволяет развернуть код за считанные секунды.

Они размещались на более чем 25 машинах Amazon High-CPU Extra-Large. Поскольку сам сервер не имеет состояния, когда им нужно было обработать больше запросов, они могли добавить больше машин.

Общее хранилище данных

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

  1. последние актуальные идентификаторы с фотографиями

  2. реальные фотографии, соответствующие этим идентификаторам фотографий

  3. пользовательские данные для этих фотографий

База данных: Postgres

Сеанс: Сервер приложений получает последние соответствующие идентификаторы фотографий из Postgres.

Сервер приложений будет получать данные из PostgreSQL, в котором хранится большая часть данных Instagram, таких как метаданные пользователей и фотографий.

Соединения между Postgres и Django были объединены в пул с помощью Pgbouncer.

Instagram разделил свои данные из-за большого объема получаемых данных (более 25 фотографий и 90 лайков в секунду). Они использовали код для сопоставления нескольких тысяч «логических» фрагментов с несколькими физическими фрагментами.

Интересная задача, с которой столкнулся и которую решил Instagram, — это генерация идентификаторов, которые можно было бы сортировать по времени. Итоговые идентификаторы с сортировкой по времени выглядели следующим образом:

  • 41 бит для времени в миллисекундах (даёт нам 41 год идентификаторов с настраиваемой эпохой)

  • 13 бит, которые представляют логический идентификатор сегмента

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

(Вы можете прочитать больше здесь.)

Благодаря идентификаторам с сортировкой по времени в Postgres сервер приложений успешно получил последние соответствующие идентификаторы фотографий.

Хранилище изображений: S3 и Cloudfront

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

В Amazon S3 хранилось несколько терабайт фотографий. Эти фотографии были быстро предоставлены пользователям с помощью Amazon CloudFront.

Кэширование: Redis и Memcached

Сеанс: Чтобы получить данные пользователя из Postgres, сервер приложений (Django) сопоставляет идентификаторы фотографий с идентификаторами пользователей с помощью Redis.

Instagram использовал Redis для хранения сопоставления около 300 миллионов фотографий с идентификатором пользователя, который их создал, чтобы знать, какой фрагмент запрашивать при получении фотографий для основного канала, ленты активности и т. д. Всё, что в Redis хранилось в памяти для уменьшения задержки, и он был разделен на несколько машин.

Благодаря грамотному хешированию Instagram смог хранить 300 миллионов сопоставлений ключ-значение менее чем в 5 ГБ.

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

Сеанс: Благодаря эффективному кэшированию с использованием Memcached получение пользовательских данных из Postgres происходило быстро, поскольку ответ был недавно кэширован.

Для общего кэширования Instagram использовал Memcached. На тот момент у них было 6 экземпляров Memcached. Memcached относительно просто наложить поверх Django.

Интересный факт: два года спустя, в 2013 году, Facebook опубликовал знаковую статью о том, как они масштабировали Memcached, чтобы обрабатывать миллиарды запросов в секунду.

Сеанс: Теперь пользователь видит главную ленту, заполненную последними фотографиями людей, на которых он подписан.

Настройка master-replica

И Postgres, и Redis работали в конфигурации «master-replica» и использовали моментальные снимки Amazon EBS (Elastic Block Store) для частого резервного копирования систем.

Push-уведомления и асинхронные задачи

Сеанс: Теперь предположим, что пользователь закрывает приложение, но затем получает push-уведомление о том, что друг опубликовал фотографию.

Это push-уведомление было отправлено с помощью pyapns, как и более миллиарда других push-уведомлений, которые Instagram уже отправил. Pyapns — это универсальный поставщик службы push-уведомлений Apple (APNS) с открытым исходным кодом.

Сеанс: Пользователю очень понравилось это фото! Поэтому он решил поделиться этим в Твиттере.

На серверной стороне задача помещается в Gearman — очередь задач, которая передает работу более подходящим машинам. В Instagram было около 200 воркеров на Python, использующих очередь задач Gearman.

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

Мониторинг

Сеанс: Ой-ой! Приложение Instagram вышло из строя из-за того, что на сервере произошла ошибка и был отправлен ошибочный ответ. Трое инженеров Instagram получают мгновенное оповещение.

Instagram использовал Sentry, приложение Django с открытым исходным кодом, для мониторинга ошибок Python в режиме реального времени.

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

Pingdom использовался для мониторинга внешних служб, а PagerDuty использовался для обработки инцидентов и уведомлений.

Финальный обзор ранней архитектуры

Комментарии (11)


  1. Timofeuz
    16.09.2023 15:47
    +3

    В Instagram было около 200 сотрудников Python


    1. pudovMaxim
      16.09.2023 15:47

      Бедные сотрудники, вручную обрабатывали запросы от 14 миллионов клиентов)


  1. yrub
    16.09.2023 15:47
    +2

    ничего особого, куда интересней узнать как они завирусились


    1. bel1k0v Автор
      16.09.2023 15:47

      Мне кажется дело в Амазон


      1. vorphalack
        16.09.2023 15:47

        по мне — так ИлИтАрНаСтЬ и выход iphone 3G/3GS, у которых были первые нормальные камеры среди массовых смартов. там же в оригинале не котиков постили, а "смотрите как я лухари живу!"


  1. zzzzzzerg
    16.09.2023 15:47
    +2

    Для тех, кто как и я не понял, что означает слово Сеанс, то в оригинале это Session (которое конечно можно перевести как Сеанс), но по смыслу большое подходит "a period devoted to a particular activity."


    1. bel1k0v Автор
      16.09.2023 15:47
      +1

      "Сессия" мне не понравилась, и вообще никогда не нравилась


      1. zzzzzzerg
        16.09.2023 15:47

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


        1. bel1k0v Автор
          16.09.2023 15:47

          Вы в кино не были?


  1. plFlok
    16.09.2023 15:47
    +2

    Как?

    Ранняя инфраструктура Instagram работала на AWS

    Занесли денег за аутсорс облако


  1. Algrinn
    16.09.2023 15:47

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