ТехнофITнес для тимлидов и разработчиков
@id780444464808_bizПодкачивай хард-скиллы и держи техническую форму с регулярными разборами ключевых IT материалов: архитектура, базы данных, производительность и системный дизайн.
Динамика подписчиков
Последние записи
Нюансы паттерна Retry Ещё одна классная статья от Яндекса, на этот раз о особенностях паттерна Retry. Она продолжает тему идемпотентности (если не читали, начните с неё — вот [/8|ссылка на пост]) и объясняет, как простое решение может создать множество проблем в высоконагруженных системах. Сам по себе Retry прост как пять копеек: запрос упал — нужно повторить. Но всё становится гораздо интереснее, когда мы начинаем говорить о конфигурации повторов в высоконагруженной системе. ⭐ Интересные идеи ➡ Если API идемпотентное, запросы можно безопасно повторять, и внедрение Retry может быть хорошим решением. Однако простые перезапросы могут вызвать так называемый retry storm, который добьёт сервис, которому уже не очень хорошо. В качестве решения стоит использовать exponential backoff — экспоненциальное увеличение времени ожидания между повторными попытками. ➡ Следующий подвох: если сервису стало плохо, его клиенты могут синхронизироваться даже с учётом exponential backoff и начать слать пачки запросов в одно и то же время. В таком случае используется jitter — дополнительная случайная задержка в паузах между ретраями, которая помогает уменьшить вероятность повторного скопления запросов. ➡ Если сервис будет в нерабочем состоянии слишком долго, то даже exponential backoff не спасёт. Он лишь отложит нагрузку, но при длительном даунтайме она рано или поздно начнёт расти каскадно и точно добьёт систему. Решение: использовать паттерн Circuit Breaker. В качестве альтернативы можно использовать бюджет на ретраи, но этот подход усложняет логику клиента. Также в тексте упоминаются ещё несколько интересных паттернов, о которых я напишу позже. Приятного чтения! ➖➖➖➖➖➖➖➖➖➖➖ // Понравился пост? Ставь 💛 // И обязательно подпишись на канал, чтобы не пропустить новые статьи
Открыть в MaxАномалии транзакций и их связь с уровнями изоляции Хороший refresher по аномалиям, возникающим при выполнении транзакций в многопоточной среде. Автор верно замечает, что понимание уровней изоляции транзакций приходит только после осознания аномалий, которые могут возникнуть. Лично у меня понимание уровней изоляции сформировалось именно после детального разбора аномалий в DDIA (она же «книга с кабанчиком»). Когда понятна сама проблема, гораздо легче вникнуть в механизмы её решения. А ещё в статье есть красивые схемы и классное саммари по уровням изоляции. ⭐ Интересные идеи ➡ Мир был бы намного проще, если бы мы могли выполнять все транзакции последовательно. В принципе, это возможно, но производительность такого решения была бы ужасной. ➡ Всего три транзакции могут генерировать шесть возможных последовательностей выполнения (3! = 6). Число вариантов растёт экспоненциально, поэтому чем выше OLTP-нагрузка в системе, тем выше вероятность возникновения аномалий. ➡ Write Skew — аномалия, о которой часто незаслуженно забывают. А ведь она довольно интересная: транзакции читают одни и те же данные и на их основе выполняют изменения, что приводит к конфликтам записи. Приятного чтения! // Понравился пост? Ставь 💛 // Есть классный материал? Пришли ссылку в комментах
Открыть в MaxБалласт памяти в Go или как полюбить кучу Крайне занимательная статья о том, как в Twitch одним маленьким изменением добились снижения потребления CPU на фронтовых серверах на ~30% и уменьшили 99-й перцентиль времени ответа API на ~45%. Их приложение страдало от пиков нагрузки, в остальное время работало стабильно. При нагрузке API latency сильно деградировало. Очевидной идеей было держать дополнительные мощности, но стоимость кусалась. Потыкав pprof-ом, они выяснили, что при нагрузках огромное потребление приходится на garbage collector. Происходило множество триггеров GC (8-10 в секунду) и выделений памяти, поэтому сборщик мусора пожирал те самые ~30% CPU. ⭐ Интересные идеи ➡ Простое решение: выделили балласт на 10 GiB RAM для каждого пода. Сборщик мусора при каждом вызове удваивает память, поэтому следующий вызов увеличит кучу до 20 GiB, чего хватит надолго. ➡ Балласт не убивается GC, потому что на него висит постоянный референс из main. ➡ Балласт не потребляет столько памяти на самом деле, потому что в *nix-системах память адресуется виртуально и маппится только при реальном обращении к ней. Поэтому балласт фактически занимает место только в виртуальном адресном пространстве программы. ➡ Решение привело к уменьшению циклов GC на 99% (до 2 в минуту) и снижению потребления CPU на те самые ~30%. Ну и отказоустойчивость, конечно, повысилась. Приятного чтения! // Понравился пост? Ставь 💛 // Есть классный материал? Пришли ссылку в комментах
Открыть в MaxХорошие программисты думают о структуре данных В статье развивается идея Линуса Торвальдса о том, что думать о структуре данных — крайне важно. Линус, как всегда, выражается резко: «Плохие программисты думают о коде, хорошие — о структуре данных.» Основная мысль заключается в том, что хорошо спроектированные данные легче понимать и поддерживать. При правильном подходе они упрощают логику приложения и делают его более надёжным (как минимум за счёт сокращения избыточной сложности). Автор приводит личный опыт (к сожалению, без деталей), когда при оптимизации сложного алгоритма функцию на 500 строк заменили функцией на 50 строк и грамотно спроектированной структурой данных. ⭐ Интересные идеи ➡ Данные легче понимать, чем программную логику. Поэтому часть сложности кода можно переносить в структуру данных. Этот подход спорный, но в нём определённо есть смысл. ➡ Проектирование стоит начинать с данных. Обычная ошибка — сначала писать код, а потом прикручивать к нему данные. Правильнее сначала продумать структуру данных и строить дизайн системы от этого. ➡ Код тоже важен! Просто сначала лучше разобраться со структурой данных и взаимодействиями, а уже потом писать код. Приятного чтения! // Понравился пост? Ставь 💛 // Есть классный материал? Пришли ссылку в комментах
Открыть в MaxПросто используй Postgres Статья посвящена одной простой идее: если вы создаёте новое приложение и вам нужно персистентное хранилище, по умолчанию берите Postgres — и не парьтесь. Большая часть статьи — это ответ на вопрос «Почему не Х?» Например, почему не Mongo, SQLite, Cassandra, Kafka и т. д.? Я разделяю мнение автора и считаю, что если у вас нет каких-либо специализированных требований, то вполне разумно использовать Postgres как выбор по умолчанию. Например, один из моих рабочих проектов хранит данные в Postgres (нет специфики), а второй — в ArangoDB (нужно гулять туда-сюда по графам). ⭐ Интересные идеи ➡ Cassandra и Mongo довольно сложно настраивать, особенно в разрезе поиска данных. Если мы не знаем сценариев поиска, то получим целый мешок сложностей, которых можно было бы избежать с Postgres. ➡ Valkey (он же Redis на стероидах) больше подходит для кеширования, но его возможности масштабирования вполне позволяют организовать на его основе персистентное хранилище. Однако RAM стоит адово дорого по сравнению с ROM, поэтому вариант так себе. ➡ AI-based БД скорее представляют собой пузырь, чем полноценные решения. Как и многое в AI-мире. Скорее всего, вам достаточно будет просто написать import openai. ➡ И лишь Google Таблицы не имеют недостатков. Пользуйтесь на здоровье. ❤ Статья тут. Приятного чтения! // Понравился пост? Ставь 💛 // Есть классный материал? Пришли ссылку в комментах
Открыть в MaxИдемпотентность от А до Я Отличная статья от Яндекса про идемпотентность. Сама по себе идемпотентность — тема непростая, и традиционно о ней вспоминают только тогда, когда что-то ломается. Особенно приятно читать статью в формате живой истории, а не сухой выжимки. На таких примерах информация воспринимается легче. Например, история про звонок в 8 утра вызвала у меня холодный пот и неприятные воспоминания. ⭐ Интересные идеи ➡ Идемпотентный метод API — это метод, который при повторном вызове не меняет состояние. Однако результат вызова метода может меняться. Например, методы GET, PUT и DELETE формально идемпотентны. ➡ Для обеспечения идемпотентности применяется так называемый ключ идемпотентности — токен, сгенерированный на стороне клиента. Этот ключ предназначен для идентификации запроса на бэкенде при многократном повторении. ➡ При работе с идемпотентностью важно учитывать не только success scenario, но и различные варианты отказов. Также не стоит забывать о ретраях, таймаутах и других паттернах защиты. Приятного чтения! // Понравился пост? Ставь 💛 // Есть классный материал? Пришли ссылку в комментах
Открыть в MaxКак Figma масштабировали свою БД, часть 1 По работе мы с командой сейчас очень плотно занимаемся вопросами масштабирования БД в целом и шардирования в частности. Поэтому я довольно много смотрю/читаю всего, что связано с этой темой. На выходных прочитал замечательную эпопею о том, как Figma столкнулись с проблемами роста своей БД. У них был заряженный по железу монолитный Postgresql, который всё-таки начал упираться в свои пределы. Из интересного в статье: ➡ Базовые тактические действия, когда БД начинает не вывозить ➡ Почему Figma отказались от переезда на другие БД ➡ Как инженеры Figma делали вертикальное партиционирование (вытаскивали таблицы в отдельные базы) без даунтайма (но есть нюанс) Рекомендую к ознакомлению всем, у кого база потенциально может начать задыхаться. Будете знать, к чему готовиться 🙂 Приятного чтения! // Понравился пост? Ставь 💛 // Есть классный материал? Пришли ссылку в комментах
Открыть в Max