Простыми словами про руководящие принципы и стек технологий
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. Поскольку сам сервер не имеет состояния, когда им нужно было обработать больше запросов, они могли добавить больше машин.
Общее хранилище данных
Сеанс: Сервер приложений видит, что запросу нужны данные для основного фида. Для этого, скажем, необходимо:
последние актуальные идентификаторы с фотографиями
реальные фотографии, соответствующие этим идентификаторам фотографий
пользовательские данные для этих фотографий
База данных: 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)
yrub
16.09.2023 15:47+2ничего особого, куда интересней узнать как они завирусились
bel1k0v Автор
16.09.2023 15:47Мне кажется дело в Амазон
vorphalack
16.09.2023 15:47по мне — так ИлИтАрНаСтЬ и выход iphone 3G/3GS, у которых были первые нормальные камеры среди массовых смартов. там же в оригинале не котиков постили, а "смотрите как я лухари живу!"
zzzzzzerg
16.09.2023 15:47+2Для тех, кто как и я не понял, что означает слово Сеанс, то в оригинале это Session (которое конечно можно перевести как Сеанс), но по смыслу большое подходит "a period devoted to a particular activity."
bel1k0v Автор
16.09.2023 15:47+1"Сессия" мне не понравилась, и вообще никогда не нравилась
zzzzzzerg
16.09.2023 15:47На мой взгляд, Сеанс только запутывает. По смыслу (опять же на мой взгляд) это больше похоже на спринт или релиз, но надо наверное знать как устроены были процессы разработки в команде в тот период. По описанию похоже на "навалились и сделали".
plFlok
16.09.2023 15:47+2Как?
Ранняя инфраструктура Instagram работала на AWS
Занесли денег за
аутсорсоблако
Algrinn
16.09.2023 15:47Как увеличился? Аналитики просто очень глубоко разбирались в психологии гламурных кис и сумели создать продукт, который хорошо покрывал их потребности. А остальное дело техники.
Timofeuz
pudovMaxim
Бедные сотрудники, вручную обрабатывали запросы от 14 миллионов клиентов)