ТехнофITнес | Никита Ульшин – Telegram
ТехнофITнес | Никита Ульшин
295 subscribers
3 photos
53 links
Подкачивай хард-скиллы и держи техническую форму с регулярными разборами ключевых IT материалов: архитектура, базы данных, производительность и системный дизайн.

По всем вопросам и рекламе: @NikitaUlshin
Download Telegram
10 техник для снижения стоимости Kubernetes

Отказоустойчивость стоит дорого. Иногда — ОЧЕНЬ дорого. А временами — просто космически дорого. На масштабе даже небольшие и очень простые техники могут вылиться в экономию значительного количества денег.

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

Меня лично больше всего порадовала техника №2: подумайте об архитектуре. Старая как мир истина гласит: чем раньше заметили проблему — тем дешевле её исправить. Пофиксить всякие мелочи легко, а вот исправить архитектурные проблемы стоит диких денег.

⭐️ Интересные идеи

➡️ Выбор одного провайдера. Автор рекомендует не разворачиваться на разных облаках, потому что у них будут разные надстройки и нюансы. Такую инфраструктуру сложнее обслуживать и развивать. Из минусов — в таком подходе мы получаем vendor lock, что тоже может выстрелить в ногу.

➡️ Правильные настройки. Чем точнее настроен кубер, тем меньше ресурсов будет тратиться впустую. Лимиты, квоты, скейлинг, сайзинг — всё это требует тщательного анализа и подстройки под конкретные задачи.

➡️ Мониторинг — важная часть снижения костов, потому что иначе будет сложно понять, где ресурсы тратятся впустую.

➡️ Культура превыше всего. Техники работают прекрасно, но если в компании нет культуры отслеживания расходов и эффективности, то все оптимизации будут напоминать прикладывание подорожника к открытому перелому.

Приятного чтения!

#highload@tech_fit #kubernetes@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥53👍3
System Design: Spotify

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

В этой статье автор показывает, как бы он спроектировал Spotify на собеседовании. Решение получилось очень любопытным и при этом достаточно простым. Правда, я споткнулся на терминологии leader-follower (не сразу понял, что теперь master-slave так называется).

Тем, кому предстоит проходить подобное собеседование, рекомендую также обратить внимание на последовательность шагов, которые предпринимает автор. Сначала он выяснил требования и посчитал циферки, а только потом начал рисовать. Не наоборот.

В примере, конечно, не хватает ряда цифр (например, расчёта RPS) и адекватного проектирования бэкенда (web servers — это сильно). Но сама идея как минимум достойна изучения. У меня в закладках есть более интересные примеры проектирования таких систем, так что ждите новых постов.

⭐️ Интересные идеи

➡️ Основная проблема — для песен нужно много места (90 ТБ). Для их хранения автор выбрал обычное файловое хранилище (типа S3). Метаданные хранятся в обычной реляционной базе — их совсем немного.

➡️ Боттлнеком в такой системе становится нагрузка на сеть. Если постоянно читать все песни и гонять трафик, то в какой-то момент пропускной способности просто перестанет хватать. Решение простое — внедрить региональные CDN, которые будут кэшировать и раздавать песни по своей области покрытия.

➡️ На самом деле под капотом Spotify работает по запатентованному P2P-протоколу синхронизации, поэтому у них в системе нет централизованного хранилища. Эта информация есть в первом комментарии к статье — там же содержится ссылка на сам документ с описанием протокола.

Приятного чтения!

#systemdesign@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍5🔥43
Почему "nit" — это плохо?

В код-ревью периодически применяются комментарии типа “nit”. Обычно ими обозначают места, которые можно сделать лучше, но это не критично. Чаще всего такие комментарии касаются вопросов стиля или оформления кода. Также в категорию “nit” попадают частные мнения ревьюеров, которые не влияют на качество конечного результата.

В статье автор показывает, что на самом деле nit не так прост, как кажется, и почему такие комментарии могут даже вредить. Он проанализировал 25 000 nit-комментариев, чтобы понять, к чему они относятся и насколько они на самом деле являются nit.

⭐️ Интересные идеи

➡️ В целом термин nit трактуется очень широко, поэтому и применяться может разными людьми по-разному. То, что для одного — мелочь, для другого может быть принципиальным вопросом (табы vs пробелы).

➡️ Чаще всего nit-комментарии касаются форматирования: точек с запятыми, пробелов и так далее (god bless gofmt). На втором месте находится организация кода, на третьем — написание документации и комментариев.

➡️ Многие nit-комментарии можно убрать, настроив линтеры и автоформаттеры кода. Даже логику можно покрыть линтерами (например, поставить ограничения на длину функции или количество логических ветвлений).

➡️ Основная беда nit-комментариев заключается в том, что комментарии дорого стоят с точки зрения разработки. Одному человеку нужно проанализировать код и написать комментарий, другому — проанализировать комментарий и внести изменения или аргументировать отказ от этого (и пошло-поехало). Хорошо настроенные форматтеры и линтеры могут заметно ускорить и упростить код-ревью.
Приятного чтения!

#programming@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥31👍1
JSON_TABLE в Postgres 17 не так уж крут

В релизе Postgres 17 появилась функция JSON_TABLE. Она обрабатывает JSON и выдаёт данные в виде обычного реляционного представления. Прелесть в том, что потом к этим данным можно обращаться с помощью стандартных SQL-операторов.

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

Автор статьи считает, что JSON_TABLE — это всего лишь синтаксический сахар, который не вносит кардинальных изменений в работу с базой данных. Подробности — в статье.

⭐️ Интересные идеи

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

➡️ JSON_TABLE значительно упрощает условия WHERE, и чем сложнее выборка из JSON, тем заметнее это упрощение.

➡️ Реальную пользу JSON_TABLE начинает приносить только тогда, когда запросы становятся действительно сложными. Чем больше у вас группировок и фильтраций по JSON, тем аккуратнее выглядит синтаксис запроса. Вопрос только в том, зачем вы вообще храните такие данные в Postgres в виде JSON. :)

Приятного чтения!

#databases@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥32👍1
Каждый бэкендер должен уметь работать с платежами

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

Поэтому обработка платежей должна быть надёжной и отказоустойчивой. Как ни странно, многого можно добиться с помощью простого (но очень тщательно настроенного) Retry. В статье автор показывает, как именно это можно реализовать.

⭐️ Интересные идеи

➡️ Статусы платежей нужно хранить в append-only хранилище. Автор предлагает использовать отдельную базу данных, но подойдёт и обычная таблица. Такой подход даёт историю изменений, защищает от порчи существующих данных и хорошо работает в многопоточной среде.

➡️ Важно чётко понимать, когда нужно делать ретрай, а когда — нет. Ретраим таймауты, ошибки доступности систем и срабатывание рейт-лимитов. Не ретраим ошибки бизнес-логики — вроде недостатка средств или некорректных данных карты.

➡️ Если ретраи закончились, ошибка должна попадать в Dead Letters Queue. Это важно, потому что такие ошибки стоит анализировать отдельно. Возможно, там зарыты системные баги или недоработки бизнес-процессов.

➡️ Обеспечьте exactly-once обработку. Клиент вряд ли обрадуется, если с его карты спишется оплата дважды. Поэтому используйте ключи идемпотентности и аккуратно работайте с распределёнными транзакциями.

Приятного чтения!

#systemdesign@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍32🔥2
Как не стоит сортировать по рейтингу

Годы идут, технологии меняются, но многие приложения так и не научились делать нормальную сортировку по рейтингу. Товары с одной оценкой в 5 выдаются на более высоких позициях, чем товары с 1000 оценками и рейтингом 4.99.

Такая сортировка ухудшает клиентский опыт и в целом выглядит стрёмно. В статье (довольно старой, но как никогда актуальной) автор разбирает типичные ошибки и показывает, как надо делать.

⭐️ Интересные идеи

➡️ Просто вычесть отрицательные оценки из положительных — плохая идея. Она не учитывает общее соотношение положительных и отрицательных отзывов, а также их количество.

➡️ Просто считать средний рейтинг — тоже плохая идея. В итоге получим ситуацию, которую я описал во введении. Средний рейтинг тоже не учитывает количество оценок.

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

➡️ В этот расчёт также заложен статистический доверительный уровень — вероятность, с которой можно доверять рассчитанной нижней границе.

В самой статье также есть примеры реализации на Python и SQL (они гораздо проще, чем сама формула).

Приятного чтения!

#systemdesign@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
25👍3🔥3
Шардирование Postgres в Notion

Я вообще неровно дышу к теме шардирования с тех пор, как мы на работе запилили cookbook по шардированию на стороне клиента. Уже тогда я прочитал кучу статей на эту тему, но всё равно продолжаю открывать для себя новые любопытные нюансы.

В сегодняшней статье инженеры из Notion рассказывают, как они шардировали свой Postgres и что из этого получилось.

⭐️ Интересные идеи

➡️ Шардирование было вопросом времени, но решение приняли, когда VACUUM начал стабильно зависать. Сам по себе диск — не проблема, но это могло привести к достижению предела идентификаторов транзакций, что заблокировало бы все записи в БД.

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

➡️ Шардирование решили делать на стороне клиента (приложения). Для этого нужно было ответить на три вопроса: какие данные будут шардироваться? Каким образом их разделить? Сколько нужно шардов и как их организовать?

➡️ Вся модель Notion крутится вокруг блока (block), поэтому шардировать они решили все таблицы, достижимые по связям от таблицы блоков. Это позволяло хранить связанные сущности на одном физическом шарде и избежать кроссшардовых запросов.

➡️ В качестве partition key выбрали workspace id (идентификатор рабочего пространства), поскольку в их структуре данных блок относится строго к одному воркспейсу.

➡️ Для миграции на шарды использовали двойную запись через журнал изменений: дублировали запись и в монолитную БД, и в лог, откуда переправляли её в шард. По сути, реализовали свою логическую репликацию, потому что обычная не справилась с шагом создания изначального снепшота.

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

Приятного чтения!

#systemdesign@tech_fit #databases@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥53👍3
Что может сломать микросервисы при переезде с монолита?

Миграция с монолита на микросервисы уже стала притчей во языцех. Я уж молчу про миграции с микросервисов на монолит.

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

⭐️ Интересные идеи

➡️ Первая же классика — пошаренные библиотеки вроде модуля авторизации/аутентификации. Вроде как развязали микросервисы, а часть логики спрятана в такой либе — и вот мы получаем кучу багов.

➡️ Второй любимчик — расшаренные доменные модели. Бывает вполне ок, когда, скажем, какой-нибудь заказ собирается из десятка микросервисов. Не ок, когда этот заказ зашит в какую-то либу, которая может поломать целую кучу сервисов.

➡️ Третьим пунктом идут нетленные common-utils. В каждом проекте, который я встречал в своей жизни, есть такая папка-франкенштейн, в которой переизобретены все велосипеды мира. В микросервисах эта папочка рискует стать библиотекой и вестником проблем.

➡️ Автор прикольно называет такую структуру “Звезда смерти” (микросервисы, завязанные на одной либе, и правда звёздочку напоминают).

Приятного чтения!

#microservices@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
23👍3🔥3
The Deadlock Empire

В эти длинные выходные хочу поделиться необычной рекомендацией. The Deadlock Empire – это не статья, а полностью бесплатная обучалка по работе с конкурентностью.

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

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

Идеальная штука, чтобы поразвлекаться на выходных с пользой. Приятного исследования!

#programming@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
3🔥8👍32
Паттерны микросервисов: SAGA

Одна из вещей, которая так прекрасна в монолите — возможность никогда не сталкиваться с eventual consistency. Всё обмазано ACID-транзакциями, всё просто и понятно. Не жизнь, а сказка!

С приходом микросервисов сказка становится страшной. ACID-свойства нам больше недоступны, данные размазаны по нескольким базам, а консистентность всё равно как-то нужно поддерживать. Тут на сцену выходит паттерн Сага, о котором и рассказывается в статье.

Статья описывает паттерн Сага, способы организации саг, возможные аномалии и контрмеры по борьбе с ними.

⭐️ Интересные идеи

➡️ Конечно, существуют распределённые транзакции. Проблема в том, что многие технологии не поддерживают протокол двухфазного коммита, что ограничивает нас в выборе технологий. Плюс, 2PC ещё и очень хрупкий.

➡️ Сага — это не распределённая транзакция, а фактически механизм выполнения и контроля необходимого множества локальных транзакций в целевых микросервисах. По сути, сага является пошаговой реализацией некоторого бизнес-процесса.

➡️ Для отката транзакций в сагах используются “компенсирующие транзакции” — специальные шаги, которые возвращают состояние системы в нужную точку.

➡️ Основная проблема в сагах — это координация действий. Есть два варианта: оркестрация и хореография. Оркестрация заключается в использовании специального координационного сервиса (оркестратора), хореография же перекладывает ответственность за обработку и посылку сигналов на сами сервисы-участники.

➡️ Оркестрация более понятна и удобна, но создаёт single point of failure. Хореография более надёжна и проста в разработке, но ей гораздо сложнее управлять, а понимание процесса может быть крайне нетривиальной задачей.

➡️ Одна из главных проблем в сагах — отсутствие изолированности, как у классических транзакций. Это вызывает аномалии, в частности “грязные чтения”, “неповторяемые чтения” и “потерянные обновления”.

➡️ Одной из контрмер является semantic lock — пометка сущности как взятой в работу, чтобы её нельзя было изменить повторно. Например, в случае с заказом мы можем пометить его как “*_PENDING”, и другие запросы будут знать, что этот заказ трогать не нужно.

➡️ Главная контрмера против проблем с сагами — не использовать саги грамотный дизайн самих саг. Он позволяет избежать множества проблем. Многие из них можно увидеть и устранить ещё на этапе проектирования саги, просто убрав лишние шаги или изменив порядок действий.

Приятного чтения!

#microservices@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥42👍2
System Design — одна из самых сложных секций на собеседовании

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

Хотя секция дизайна и сложна, к ней тоже можно подготовиться. Я провожу такие секции и собрал чек-лист по подготовке к системному дизайну. Вот, что внутри:

Алгоритм из 7 шагов по прохождению системного дизайна
Примеры задач, которые могут попасться на секции
Частые ошибки и как их обойти
Список ресурсов: от базовых до продвинутых

Если готовишься к собесам — забери.
Если не готовишься — всё равно пригодится, чтобы структурировать мышление.

Чек-лист доступен подписчикам. Жми кнопку ниже — получишь инструкцию, как его получить.
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍21🔥75
Обзор кэширования (с паттернами)

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

В мире программирования есть две наиболее сложные проблемы: как назвать переменную и как инвалидировать кэш. Попробуем сегодня немного разобраться со вторым.

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

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

⭐️ Интересные идеи

➡️ Некоторые паттерны (например, Write Through и Write Back) могут значительно снизить нагрузку на БД, но при этом имеют риски потери данных. Может здорово пригодиться в нагруженных системах, где потери некоторых данных не так критичны.

➡️ Refresh-Ahead — очень интересный паттерн, при котором данные в кэше обновляются асинхронно, что (теоретически) позволяет вообще не ходить в БД. Я использовал этот паттерн в одной из систем пару лет назад — он позволяет круто снизить нагрузку.

➡️ У кэша есть несколько разных стратегий вытеснения, которые могут пригодиться в разных ситуациях. Иногда бывает полезно очистить даже самые “горячие” данные, если “холодные” будут использоваться с большей вероятностью.

Приятного чтения!

#systemdesign@tech_fit #databases@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍433🔥3
Исправляем дублирование запросов к API

Меня безумно порадовала первая же строка этой статьи:

«Первое правило распределённых систем — не превращайте свою систему в распределённую.»


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

Одна из таких проблем — дублирующие запросы к API. Распределённые системы лишены ACID-транзакций (в лучшем случае можно применить сагу), поэтому дублирующие запросы на чувствительные операции могут вызвать трудноустранимые баги. Решением является идемпотентность, которой и посвящена статья.

⭐️ Интересные идеи

➡️ Идемпотентность — это свойство операций, которое позволяет применять их многократно без изменения конечного состояния приложения. Идемпотентны методы GET, PUT, DELETE, HEAD, OPTIONS и TRACE. POST и PATCH не являются идемпотентными.

➡️ Для обеспечения идемпотентности используется отслеживание пар ключ–запрос. Ключ генерируется на клиенте для каждого запроса и называется ключом идемпотентности.

➡️ Для ключа идемпотентности предусмотрен специальный HTTP-заголовок Idempotency-Key. Он принимает строку; в качестве примера спецификация использует UUID.

➡️ Спецификация также описывает обработку ошибок. Указаны три статуса:
🟡400 — не указан ключ идемпотентности
🟡422 — ключ идемпотентности уже использован
🟡409 — запрос с указанным ключом идемпотентности уже обрабатывается

Приятного чтения!

#systemdesign@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
3🔥72👍2
Слой абстракции над Key-Value от Netflix

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

В сегодняшней статье разбирается слой абстракции (Data Abstraction Layer, DAL) над Key-Value-хранилищами, разработанный Netflix как способ борьбы с расширением технологического стека хранилищ компании.

Netflix часто применяет самые современные решения в своих системах, но это приводило к тому, что инженерам приходилось постоянно переучиваться на новые технологии — разбираться с гарантиями хранилищ, их подходом к моделированию данных и так далее. Вдобавок приходилось следить за изменениями в нативных API множества БД. Управлять таким адским зоопарком стало очень сложно.

⭐️ Интересные идеи

➡️ В качестве решения инженеры Netflix решили написать свой сервис для работы с KV-хранилищами. Это позволило скрыть нюансы работы с конкретной базой за абстракцией и сделать API более стабильным.

➡️ Основная модель данных хранилища — двухуровневый map. Первый уровень — ID (primary key), второй — сортированный map байтовых пар (SortedMap<bytes, bytes>). Такая структура данных позволяет эффективно закрывать большинство use cases.

➡️ Для физического и логического разделения данных используются namespaces. В namespace также записываются конфигурация доступа к данным и параметры хранилища. Например, можно задать уровень согласованности.

➡️ Для больших кусков данных используется умное разделение на чанки. Если запись >1 МБ, то в основном хранилище хранятся только ID, ключ и метаданные, а сами данные делятся на маленькие чанки и складываются в отдельное хранилище.

➡️ Для пагинации ограничение сделано в байтах, а не в количестве сущностей на страницу. Так инженеры обеспечивают высокий SLO (единицы миллисекунд на операцию чтения страницы в 2 МиБ). Но этот подход создаёт и свои сложности, потому что многие базы поддерживают только «поштучную» пагинацию. Поэтому для них пришлось писать свои костыли.

➡️ Также дополнительно реализована адаптивная пагинация. Поскольку пагинация опирается на объём данных, а не количество сущностей, важную роль начинает играть средний размер сущности в namespace. Поэтому сервис DAL постоянно вычисляет и кэширует это значение, опираясь на него для fine tuning запросов на получение данных.

Приятного чтения!

#highload@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍3🔥31
Внутри S3

Отличный доклад от инженеров из Яндекса о том, как у них устроено хранилище S3. А для любителей послушать — есть запись доклада с конференции.

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

⭐️ Интересные идеи

➡️ Инженеры Яндекса разработали свой сервис для работы напрямую с жёсткими дисками. Он держит более 1,000,000 RPS и работает с триллионами файлов. Про него есть отдельный доклад, который я позже обязательно посмотрю и напишу обзор. Для особо любопытных — вот ссылка.

➡️ В схему работы сразу заложено динамическое шардирование. Статика не подходит по совершенно понятной причине — добавлять бакеты будет очень сложно, а файловое хранилище точно будет быстро расти.

➡️ Фоном работают несколько процессов: mover перетаскивает чанки между бакетами, splitter делит жирные чанки на более мелкие. Процессы блокируют чанк на запись, но работают единицы секунд, поэтому негативное влияние на клиента незначительно.

➡️ Для многих внутренних процессов важно корректно вычислять счётчики (тот же расчёт квот), но при подсчёте «в лоб» они обычно страдают от конкурентности. Решением стала очередь счётчиков: каждое изменение складывается в специальную очередь, которую разгребает фоновый процесс. Этот же процесс используется для биллинга, потому что видит все изменения в бакетах.

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

Приятного чтения!

#highload@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥53👍2
Прогрев кэша в стиле Netflix

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

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

Проблем добавляла и инфраструктура AWS, которая регулярно вырубает ноды кэша по каким-то своим причинам, что вызывало сильные просадки по latency (представляете, что будет, если на нагрузках Netflix просто погасить кэш?).

⭐️ Интересные идеи

➡️ В качестве решения была создана инфраструктура прогрева кэша. Она делится на две смысловые части: прогрев реплик и прогрев инстансов.

➡️ Само решение состоит из трёх компонентов: Controller, Dumper, Populator. Controller выполняет роль оркестратора и очищает ресурсы, Dumper создаёт дампы кэша (спасибо, кэп), Populator накатывает дампы на новые реплики.

➡️ Dumper и Populator общаются через SQS-очередь, которая создаётся специально для них контроллером. Dumper заливает данные на S3 и кладёт ID чанка в очередь, Populator вычитывает их и накатывает на ноду. Операция считается завершённой, когда очередь пуста — Controller удаляет её и инстансы Dumper/Populator.

Приятного чтения!

#highload@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍72🔥1
Как архитектура LinkedIn позволяет находить сообщение за 150мс

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

Инженеры LinkedIn изрядно заморочились над архитектурой поиска. Подробнее — в статье.

⭐️ Интересные идеи

➡️ Основой архитектуры стали два вывода. Во-первых, пользователь может искать только по своим сообщениям, что позволяет строить индекс на основе его инбокса. Во-вторых, не все пользователи пользуются поиском, поэтому имеет смысл строить индекс только для тех, кто это делает (строить индексы — довольно дорого по ресурсам).

➡️ Для хранения сообщений используется KV store RocksDB. Сообщения хранятся в значениях по ключу вида MemberId | ConversationId | MessageId.

➡️ Для поиска строится инвертированный индекс, используется Apache Lucene (которая, например, лежит в основе OpenSearch). Для построения индекса фразы токенизируются и сохраняются в виде карты токен-сообщения.

➡️ Индекс создаётся лениво — когда пользователь делает запрос на поиск. При запросе вытаскиваются все сообщения пользователя из RocksDB и выстраиваются в in-memory индекс, который используется для ускорения дальнейших операций поиска.

➡️ Индексы партиционируются и распределяются по разным нодам, чтобы не перегружать одну. Для координации используется Zookeeper и sticky routing.

➡️ Про TTL индекса статья умалчивает.

Приятного чтения!

#systemdesign@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥42👍2
Тейва Харшани «100 ошибок Go и как их избежать»

Пришло время и в этом канале открыть мою любимую рубрику — обзоры книг!

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

Конечно же, базовые книжки я прочитал ещё на стадии изучения языка. Но с тех пор как-то руки не доходили почитать что-то конкретно про Go — я больше читал про архитектуру, распределённые системы и базы данных. И тут произошло неожиданно приятное событие: ко мне пришли ребята из издательского дома «Питер» и предложили сделать обзор на обновлённое издание книги «100 ошибок Go».

Конечно, я не мог отказаться от обзора очередной интересной книги. Тем более что «100 ошибок Go» — книга не для новичков. Но обо всём по порядку.

⭐️ О чём книга

Как следует из названия, книга посвящена разбору 100 примеров ошибок и неэффективной работы в языке Golang. Глобально ошибки разбиты на смысловые разделы: организация кода, обработка ошибок, конкурентность и так далее.

Что можно узнать из книги:
➡️ Как грамотно использовать интерфейсы
➡️ Как выстрелить себе в ногу, перепутав длину и ёмкость среза
➡️ Чем всё-таки отличается конкурентность от параллелизма
➡️ Как создать race condition с помощью оператора append
➡️ И многое другое :)

⭐️ 3 идеи из книги

В Go интерфейс создаётся на уровне клиента. Это непривычно для программистов типа меня, которые обычно определяют интерфейс как абстракцию доступа. Проблема в том, что интерфейсы в Go реализуются неявно, и поэтому код не должен навязывать абстракцию своим клиентам.

Называть пакеты в Go нужно ещё тщательнее, чем переменные. Именование пакета должно быть кратким, ёмким и отражать его возможности. Пакеты похожи на namespace из C#, и одновременно не являются ими. Знали бы вы, сколько мы времени на код-ревью тратим, придумывая нейминг пакетов…

Обработка ошибки должна быть выполнена ровно один раз. Знаю-знаю, всегда есть соблазн сделать что-то и передать ошибку дальше, но это не идиоматично. Если код обработал ошибку, то она не должна «лететь» дальше. Является ли дополнительное логирование обработкой — решайте самостоятельно :)

⭐️ Мои впечатления

Книга мне очень понравилась. Она далеко не такая простая и примитивная, как базовые руководства по Go, и посвящена разным хитрым нюансам языка. Некоторые ошибки довольно очевидны, если внимательно пройти A Tour of Go, но многие другие дали мне достаточно интересной пищи для размышлений.

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

Отдельный плюс — перевод книги. Он достаточно хорош: в процессе чтения я не спотыкался на словах и не ловил ступор. Технические книги в целом переводить непросто, и переводчики «100 ошибок Go» хорошо справились со своей задачей.

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

Приятного чтения!

#обзор_книги@tech_fit

📝 @tech_fit
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥921
Проблема long-tail запросов в распределённых системах

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

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

⭐️ Интересные идеи

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

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

➡️ Стратегий борьбы много — выбирать нужно под себя. В частности, упоминаются кэширование, оптимизация обработки, асинхронная обработка, применение circuit breaker и другие.

Приятного чтения!

#highload@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍4🔥32
Техника хеджирования для борьбы с long-tail запросами

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

Google изобрёл ещё один интересный подход под названием “хеджирование запросов”. Суть его заключается в том, что клиент отправляет один и тот же запрос ко всем узлам и, получив первый ответ, отменяет все остальные запросы. Этому паттерну и посвящена сегодняшняя статья.

⭐️ Интересные идеи

➡️ Паттерн в первую очередь направлен на получение приемлемой latency. К примеру: у нас есть 20 нод, у каждой P99 составляет 1 секунду. С вероятностью 18,2% мы получим запрос длительностью >1 секунды. Хеджирование позволяет значительно снизить эту вероятность.

➡️ Хеджирование никак не связано с падением сервисов и не обрабатывает подобные ситуации.

➡️ За снижение вероятности попасть на long-tail запрос приходится платить многократным увеличением нагрузки. Поэтому к дизайну подобного решения нужно подходить особенно тщательно.

➡️ В Go есть готовый пакет singleflight, который позволяет избежать дублирования запросов. Остальным придётся мучиться самостоятельно :)

➡️ Альтернативное решение — изначально посылаем только один запрос. Если он вышел за предел P95, то сразу же посылаем ещё один запрос к другой ноде. Так мы получаем более сбалансированное решение: latency будет похуже, но и нагрузка будет гораздо ниже.

Приятного чтения!

#highload@tech_fit

// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥5👍42
Техника оптимизации Zero Copy в Kafka

Под высокой нагрузкой даже небольшие оптимизации могут дать заметный прирост производительности и удешевление инфраструктуры. Я помню, как коллеги по цеху за пару недель исследований снизили потребление CPU на 20% на сервисе с 10k RPS — представляете, сколько это в деньгах стоит?

Так вот, Kafka (изначально созданная для высоких нагрузок) под капотом использует много интересных оптимизаций. Одной из таких техник является Zero Copy — техника, направленная на уменьшение количества операций копирования (нет, там не всегда 0 копий).

⭐️ Интересные идеи

➡️ В случае Kafka Zero Copy выглядит так: ОС копирует данные из кэша страницы памяти напрямую в TCP socket buffer, полностью минуя программу на Java. Это позволяет убрать несколько лишних операций копирования и переключения контекста.

➡️ Kafka копирует данные с диска и посылает их по сети. При этом происходит несколько переключений контекста между приложением и ОС, а также множество операций копирования (от четырёх до бесконечности, в зависимости от объёма данных).

➡️ Поскольку Kafka хранит данные в том же формате, в котором и пересылает их, эти данные нет смысла копировать с диска в приложение, а из приложения — в TCP-буфер. Можно сделать загрузку файловых дескрипторов напрямую с диска в буфер сетевой карты (не TCP!), минуя приложение. Сетевая карта вычитывает данные по дескрипторам и отправляет их по сети.

➡️ Печальная правда: CPU редко является бутылочным горлышком Kafka, поэтому такая оптимизация не слишком влияет на общую производительность (перегруз сети случается гораздо чаще).

Приятного чтения!


// Понравился пост? Ставь 💛
// И обязательно подпишись на канал, чтобы не пропустить новые статьи
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍63🔥1