Real Time
Эволюция естественных языков — крайне занимательный процесс. Существует несколько подходов / теорий на тему того, как это происходит. Тут и фактор экономии усилий (зачем нужны лишние буквы?), фактор лени, да и просто устаревание старых терминов. Забавно что в IT этот процесс протекает исключительно быстро.
Я как уже рассказывал немного о той-самой работе Роя Филдинга, о понятии архитектура, которое она вводит, и о том что REST — это не другое название для HTTP API, а полноценный архитектурный стиль, являющийся базой для ни много ни мало стандартов HTTP 1.1 и 2.0. Наверное скоро настанет время рассказать более подробно. Тем не менее, меньше 20 лет понадобилось, чтобы изначальный смысл слова REST забылся, и теперь RESTом (или даже RESTful) зовется любое API, которое используется больше, чем единственный http метод POST и хоть как-то разумно именует url'ы, если урлы вообще есть. Это я еще не вспоминаю про гипермедиа, существование которого является совершенно необходимым условием, чтобы API мог называться REST / RESTful.
Где-то на одном уровне с RESTом по частоте неправильного использования находится и понятие real time. Слишком часто в литературе real time приравнивается к "почти мгновенно", хотя фактически этот термин имеет вообще мало отношения к скорости, а говорит скорее о гарантиях. Сегодня я расскажу что к чем и чем отличаются non real-time системы от soft / firm и hard real time.
Итак, приступим. Понятие real-time зародилось в жутко бородатые годы. Из банальной википедии следует, что самый старый цитируемый источник относится аж к 1965 году! В то время как вы понимаете, проблемы производительности IT систем очень сильно отличались от современных. POSIX тогда еще не было, домашних компьютеров в целом тоже, амазон и гугл обещали появиться через 30 лет и 33 года соответственно. Зато было много разных математиков, которые изучили разные прикольные штуки. Одной из таких штук является создание систем реального времени.
А что если бы мы могли делать системы, которые отвечают строго в рамках заданных временных границ на все запросы к ним, даже при наличии параллельных задач? Т.е. вы пихаете в систему какие-то данные, а она вам говорит "этот запрос я закончу не позже X, а этот не позже Y". Если прямо совсем цитировать википедию, система реального времени — это система, корректность которой зависит не только от логической корректности, но и от времени, когда операция была завершена. Соответственно real-time системы разделяются в зависимости от того, что будет, если не уложиться в заданные временные ограничения:
- Hard real-time системы. Не уложиться в дедлайн == отказ системы. Такие системы часто сочетают в себе механические элементы. Пример: принтер. Лазер должен светить строго в определенный момент. Не раньше и не позже.
- Firm real-time система. Пропустить дедлайн можно... но полезность результата в таком случае равняется нулю. Пример: роботы для высокочастотной торговли. Если решение не принято вовремя — его уже нет смысла принимать. Часто такие системы не включают в классификацию, так как есть еще и третий вид.
- Soft real-time системы. При пропуске дедлайна, наблюдается деградация полезности результата. Деградация при этом может быть довольно стремительная. Не получил вовремя GPS сигнал — скорее всего старый сигнал можно не ждать, так как его полностью заменит новый, но совсем небольшие опоздания в принципе допускаются.
Так вот, главная задача системы реально времени — это не высокая производительность, а постоянное время ответа. Загрузил 10 запросов, получил 10 ответов через 10 секунд. Загрузил 10000, получил 10000 через 10000 секунд. Поэтому для их реализации используются немного другие операционные системы (другая реализация шедулера задач) и немного другие библиотеки. И хоть супер-быстрый-реактивный сервис на вашем любимом языке и вправду летает, называть его системой реального времени, скорее всего не совсем корректно. А если корректно — для этого нужно показывать график с плоской чертой latency в любом процентиле, а не throughput.
Эволюция естественных языков — крайне занимательный процесс. Существует несколько подходов / теорий на тему того, как это происходит. Тут и фактор экономии усилий (зачем нужны лишние буквы?), фактор лени, да и просто устаревание старых терминов. Забавно что в IT этот процесс протекает исключительно быстро.
Я как уже рассказывал немного о той-самой работе Роя Филдинга, о понятии архитектура, которое она вводит, и о том что REST — это не другое название для HTTP API, а полноценный архитектурный стиль, являющийся базой для ни много ни мало стандартов HTTP 1.1 и 2.0. Наверное скоро настанет время рассказать более подробно. Тем не менее, меньше 20 лет понадобилось, чтобы изначальный смысл слова REST забылся, и теперь RESTом (или даже RESTful) зовется любое API, которое используется больше, чем единственный http метод POST и хоть как-то разумно именует url'ы, если урлы вообще есть. Это я еще не вспоминаю про гипермедиа, существование которого является совершенно необходимым условием, чтобы API мог называться REST / RESTful.
Где-то на одном уровне с RESTом по частоте неправильного использования находится и понятие real time. Слишком часто в литературе real time приравнивается к "почти мгновенно", хотя фактически этот термин имеет вообще мало отношения к скорости, а говорит скорее о гарантиях. Сегодня я расскажу что к чем и чем отличаются non real-time системы от soft / firm и hard real time.
Итак, приступим. Понятие real-time зародилось в жутко бородатые годы. Из банальной википедии следует, что самый старый цитируемый источник относится аж к 1965 году! В то время как вы понимаете, проблемы производительности IT систем очень сильно отличались от современных. POSIX тогда еще не было, домашних компьютеров в целом тоже, амазон и гугл обещали появиться через 30 лет и 33 года соответственно. Зато было много разных математиков, которые изучили разные прикольные штуки. Одной из таких штук является создание систем реального времени.
А что если бы мы могли делать системы, которые отвечают строго в рамках заданных временных границ на все запросы к ним, даже при наличии параллельных задач? Т.е. вы пихаете в систему какие-то данные, а она вам говорит "этот запрос я закончу не позже X, а этот не позже Y". Если прямо совсем цитировать википедию, система реального времени — это система, корректность которой зависит не только от логической корректности, но и от времени, когда операция была завершена. Соответственно real-time системы разделяются в зависимости от того, что будет, если не уложиться в заданные временные ограничения:
- Hard real-time системы. Не уложиться в дедлайн == отказ системы. Такие системы часто сочетают в себе механические элементы. Пример: принтер. Лазер должен светить строго в определенный момент. Не раньше и не позже.
- Firm real-time система. Пропустить дедлайн можно... но полезность результата в таком случае равняется нулю. Пример: роботы для высокочастотной торговли. Если решение не принято вовремя — его уже нет смысла принимать. Часто такие системы не включают в классификацию, так как есть еще и третий вид.
- Soft real-time системы. При пропуске дедлайна, наблюдается деградация полезности результата. Деградация при этом может быть довольно стремительная. Не получил вовремя GPS сигнал — скорее всего старый сигнал можно не ждать, так как его полностью заменит новый, но совсем небольшие опоздания в принципе допускаются.
Так вот, главная задача системы реально времени — это не высокая производительность, а постоянное время ответа. Загрузил 10 запросов, получил 10 ответов через 10 секунд. Загрузил 10000, получил 10000 через 10000 секунд. Поэтому для их реализации используются немного другие операционные системы (другая реализация шедулера задач) и немного другие библиотеки. И хоть супер-быстрый-реактивный сервис на вашем любимом языке и вправду летает, называть его системой реального времени, скорее всего не совсем корректно. А если корректно — для этого нужно показывать график с плоской чертой latency в любом процентиле, а не throughput.
🔥1
Maturity модели документации.
#shark_whitepaper
- Вайтпейрпер 1
- Вайтпейперт 2
Есть вбить в гугл "documentation maturnity model" возвращается какое-то немыслимое количество статей и вайтпейперов. Те две, которые я взял в качестве основы, лишь пример. Проблема документации в современных системах, на мой взгляд - это следующий этап развития глобального тренда микросервисной архитектуры, и об этом определенно стоит говорить.
Итак, в чем суть. Мы уже знаем, что микросервисы — это скорее всего будущее разработки программного обеспечения, потому что ни один другой способ разработки ПО не обеспечивает такую простоту скалирования команд, одновременно обеспечивая такой уровень доступность. Вы просто нанимаете еще одну 2-pizza team, и они начинают практически независимо от всех остальных команд приносить полезность. Как минимум так оно должно работать в теории. Но тут есть парочка больших жирные НО. На практике оказывается, что чтобы быть независимым, нужно понимать, что происходит вокруг. Тут на помощь как раз должна приходит документация, но часто ее качество оставляет желать лучшего. Сегодня я постараюсь рассмотреть понятие maturity model, на примере документации программного обеспечения.
Maturity model - это с одной стороны определитель вашего текущего уровня развитости некоторого аспекта разработка, а с другой стороны указатель на то, какие сложности есть на вашем уровне, и какой шаг нужно предпринять следующим, чтобы стать более взрослой организацией. Если речь идет о разработке ПО, их вообще довольно много. Начать можно с CMM, затем плавно перейти к SECMM CMMIВ, в общем, читать неперечитать. В случае с документацией все чуть-чуть проще, можно выделить 5 уровней развитости:
1. Неконтроллируемая / ручная документация. Основные признаки: лишь отдельные люди понимают важность и цели ведения документации. Документация редкая и неполная. Нет ни процесса ни требований к содержанию. Как правило, обновление документации - это индивидуальные усилия, которые происходят не в рамках установленных процессов, а по воле отдельно взятых личностей.
2. Полуавтоматическая / неконсистентная. Появляются стандарты ведения документации, но им следуют еще не все. Появляется возможность автоматического создания части документации (Например, openapi).
3. Полуавтоматическая / конкретная. Появляются правила, когда и в каком объеме нужно вести документацию. Стандарты к продукту документации закреплены, и все их придерживаются (продукт — это как выглядит документация, какие элементы блок-схем используются и т.д.). Появляется возможность связывать части документации между собой через гиперссылки.
4. Автоматическая / статическая. Стандарты к процессу создания документации закреплены, и все их придерживаются. Ключевое различие с предыдущем пунктом - процесс vs продукт. На 3 пункте было важно, чтобы созданная документация отвечала поставленным требованиям. На 4 уровне важность смещается в сторону процесса. Здесь необходимо, чтобы документация создавалась постоянно, при этом соответствовала правилам. Организации на таком уровне могут страдать от чрезмерной документации. Любое действие всегда описывается, но где описывается не всегда понятно, так как поиска по документации, возможно, еще нет.
5. Автоматическая / динамическая / персонализированная. Документация умеет подстраиваться под читателя. Можно выделить лишь те части, которые в настоящий момент интересны. Можно создавать свою версию документации и просматривать историчность изменений. Этот уровень недостижим без специальных инструментов для чтения и поддержки документации. Как правило, они разрабатываются внутри организации. Помимо персонализации, также должны существовать средства поиска по документации.
Что и как с этим делать? Шаг номер 1 — определить текущий уровень. Шаг номер 2 — работать над улучшениями. Здесь важно не прыгать выше головы и не решать проблемы на уровень выше. Если документация пишется хаотично и бессистемно (уровень 1) — сначала нужно систематизировать продукт документации (ур. 2), а лишь потом переходить к уровню 3 — вводить процессы по написанию этой документации
#shark_whitepaper
- Вайтпейрпер 1
- Вайтпейперт 2
Есть вбить в гугл "documentation maturnity model" возвращается какое-то немыслимое количество статей и вайтпейперов. Те две, которые я взял в качестве основы, лишь пример. Проблема документации в современных системах, на мой взгляд - это следующий этап развития глобального тренда микросервисной архитектуры, и об этом определенно стоит говорить.
Итак, в чем суть. Мы уже знаем, что микросервисы — это скорее всего будущее разработки программного обеспечения, потому что ни один другой способ разработки ПО не обеспечивает такую простоту скалирования команд, одновременно обеспечивая такой уровень доступность. Вы просто нанимаете еще одну 2-pizza team, и они начинают практически независимо от всех остальных команд приносить полезность. Как минимум так оно должно работать в теории. Но тут есть парочка больших жирные НО. На практике оказывается, что чтобы быть независимым, нужно понимать, что происходит вокруг. Тут на помощь как раз должна приходит документация, но часто ее качество оставляет желать лучшего. Сегодня я постараюсь рассмотреть понятие maturity model, на примере документации программного обеспечения.
Maturity model - это с одной стороны определитель вашего текущего уровня развитости некоторого аспекта разработка, а с другой стороны указатель на то, какие сложности есть на вашем уровне, и какой шаг нужно предпринять следующим, чтобы стать более взрослой организацией. Если речь идет о разработке ПО, их вообще довольно много. Начать можно с CMM, затем плавно перейти к SECMM CMMIВ, в общем, читать неперечитать. В случае с документацией все чуть-чуть проще, можно выделить 5 уровней развитости:
1. Неконтроллируемая / ручная документация. Основные признаки: лишь отдельные люди понимают важность и цели ведения документации. Документация редкая и неполная. Нет ни процесса ни требований к содержанию. Как правило, обновление документации - это индивидуальные усилия, которые происходят не в рамках установленных процессов, а по воле отдельно взятых личностей.
2. Полуавтоматическая / неконсистентная. Появляются стандарты ведения документации, но им следуют еще не все. Появляется возможность автоматического создания части документации (Например, openapi).
3. Полуавтоматическая / конкретная. Появляются правила, когда и в каком объеме нужно вести документацию. Стандарты к продукту документации закреплены, и все их придерживаются (продукт — это как выглядит документация, какие элементы блок-схем используются и т.д.). Появляется возможность связывать части документации между собой через гиперссылки.
4. Автоматическая / статическая. Стандарты к процессу создания документации закреплены, и все их придерживаются. Ключевое различие с предыдущем пунктом - процесс vs продукт. На 3 пункте было важно, чтобы созданная документация отвечала поставленным требованиям. На 4 уровне важность смещается в сторону процесса. Здесь необходимо, чтобы документация создавалась постоянно, при этом соответствовала правилам. Организации на таком уровне могут страдать от чрезмерной документации. Любое действие всегда описывается, но где описывается не всегда понятно, так как поиска по документации, возможно, еще нет.
5. Автоматическая / динамическая / персонализированная. Документация умеет подстраиваться под читателя. Можно выделить лишь те части, которые в настоящий момент интересны. Можно создавать свою версию документации и просматривать историчность изменений. Этот уровень недостижим без специальных инструментов для чтения и поддержки документации. Как правило, они разрабатываются внутри организации. Помимо персонализации, также должны существовать средства поиска по документации.
Что и как с этим делать? Шаг номер 1 — определить текущий уровень. Шаг номер 2 — работать над улучшениями. Здесь важно не прыгать выше головы и не решать проблемы на уровень выше. Если документация пишется хаотично и бессистемно (уровень 1) — сначала нужно систематизировать продукт документации (ур. 2), а лишь потом переходить к уровню 3 — вводить процессы по написанию этой документации
🔥1
Отзыв на Microservices Patterns.
Книги о том как правильно делать микросервисы у меня часто оставляют двоякое ощущение. Здесь тебе расписывают роскошные easy-to-use hides-complexity решения, но почему об этих решениях редко говорят на конференциях матерые инженеры... Не считая CEO компаний, которые делают IT продукты для микросервисов (как автор!) или консалтеров. С другой стороны, опыт поддержки решений в настоящем продакшене после каждой главы непристойно орет: "врёте, сударь!". Нельзя просто взять и решить проблему распределенных транзакций через Саги. Потому что, помимо проблемы технической (как это делать?), есть еще проблема поддержки. Как этот код потом менять? Как объяснить новому человеку принцип работы саги из 10 частей? Наконец, как решать проблемы, когда что-то пойдет не так? И не предлагайте мне тесты и меры предосторожности, если даже вся аутентификация в гугле может сломаться из-за бага, внесенного за пару месяцев до инцидента!
Будем считать, настроение задано. Мне редко не нравятся книги. Обычно я об этом молчу, но здесь молчать невозможно, так как паттерны микросервисов — книга, которая может вас похоронить под сложность системы, которую она предлагает создать! Давайте по существу.
Рассказ начинается с грустной истории девушки Mary — CTO компании по доставке еды Food to Go, день которой был испорчен очередным совещанием на тему, почему разработка опять продолбала все сроки. Проблема имеет глобальный характер, а значит и решать её нужно глобально — переписыванием всего на микросервисы!
В следующих главах речь идет о решении разных проблем в МС архитектуре. Везде есть ссылки на довольно удобный ресурс, где в стиле банды четырех кратко описываются те или иные паттерны. Каждая глава логически состоит из двух частей. В первой приводится теоретическое описание паттерна, его плюсы, а вот минусы почему-то иногда опускаются. Во второй идут примеры на фреймворке автора, который к тому же построен поверх Spring'а. Да, книга называется Microservices Patterns: with examples in Java не случайно. Так как фреймворк один из тех easy-to-use hides-complexity решений, вы вроде можете понять код, но это все равно что читать псевдокод, так как все спрятано под магический DSL. Как оно работает под коробкой остается загадкой. Тем более остается загадкой, как эти примеры кода можно будет использовать у себя.
Немного есть и на тему тестирования микросервисов. Здесь все стандартно, пирамида, моки, кусочек про consumer driven contract. К сожалению, нет ничего про chaos engineering, но зато есть очень много про то что end-to-end это slow и brittle и вообще не делайте их. С этой позицией я не согласен категорически! Но об этом я поворчу в следующий раз. Также есть обзор техник деплоя от "деплоим jar'ик" до "деплоим в кубер".
И наконец глава, которая практически оправдала эту книгу! Глава 13 - refactoring to microservices. Почти в конце книге находится фраза, которая могла бы поменять все мое отношение к этому произведению, если бы она была в начале. Фраза, которая даже не удостоилась фирменной рамочки, как максимально важная мысль!
> You should first try simpler solutions. If, and only if, you still have software delivery problems should you then migrate to the microservice architecture.
Тысячу раз, да! Во-первых, ни одно техническое или организационное решение не имеет смысла, вне контекста проблемы! Во-вторых, любое решение — это компромисс (trade-off). При чем компромисс не только между "здесь у нас такие-то технические свойства, а здесь сякие-то", но также между "время можно потратить на это или на то". Кто из вас с пустым беклогом, пусть первый бросит в нее камень! Между простым и быстрым решением, которое почти решит проблему и сложным и долгим, которое решит её полностью, часто правильным будет первое, а не второе.
А что касается книги, если у вас и так гора опыта и bullshit фильтр выкручен на максимум — смело читайте, не повредит. Листинги можно пропускать. Если вы только знакомитесь с миром микросервисов, начните лучше с Фаулера, а затем переходите к его гайду.
Книги о том как правильно делать микросервисы у меня часто оставляют двоякое ощущение. Здесь тебе расписывают роскошные easy-to-use hides-complexity решения, но почему об этих решениях редко говорят на конференциях матерые инженеры... Не считая CEO компаний, которые делают IT продукты для микросервисов (как автор!) или консалтеров. С другой стороны, опыт поддержки решений в настоящем продакшене после каждой главы непристойно орет: "врёте, сударь!". Нельзя просто взять и решить проблему распределенных транзакций через Саги. Потому что, помимо проблемы технической (как это делать?), есть еще проблема поддержки. Как этот код потом менять? Как объяснить новому человеку принцип работы саги из 10 частей? Наконец, как решать проблемы, когда что-то пойдет не так? И не предлагайте мне тесты и меры предосторожности, если даже вся аутентификация в гугле может сломаться из-за бага, внесенного за пару месяцев до инцидента!
Будем считать, настроение задано. Мне редко не нравятся книги. Обычно я об этом молчу, но здесь молчать невозможно, так как паттерны микросервисов — книга, которая может вас похоронить под сложность системы, которую она предлагает создать! Давайте по существу.
Рассказ начинается с грустной истории девушки Mary — CTO компании по доставке еды Food to Go, день которой был испорчен очередным совещанием на тему, почему разработка опять продолбала все сроки. Проблема имеет глобальный характер, а значит и решать её нужно глобально — переписыванием всего на микросервисы!
В следующих главах речь идет о решении разных проблем в МС архитектуре. Везде есть ссылки на довольно удобный ресурс, где в стиле банды четырех кратко описываются те или иные паттерны. Каждая глава логически состоит из двух частей. В первой приводится теоретическое описание паттерна, его плюсы, а вот минусы почему-то иногда опускаются. Во второй идут примеры на фреймворке автора, который к тому же построен поверх Spring'а. Да, книга называется Microservices Patterns: with examples in Java не случайно. Так как фреймворк один из тех easy-to-use hides-complexity решений, вы вроде можете понять код, но это все равно что читать псевдокод, так как все спрятано под магический DSL. Как оно работает под коробкой остается загадкой. Тем более остается загадкой, как эти примеры кода можно будет использовать у себя.
Немного есть и на тему тестирования микросервисов. Здесь все стандартно, пирамида, моки, кусочек про consumer driven contract. К сожалению, нет ничего про chaos engineering, но зато есть очень много про то что end-to-end это slow и brittle и вообще не делайте их. С этой позицией я не согласен категорически! Но об этом я поворчу в следующий раз. Также есть обзор техник деплоя от "деплоим jar'ик" до "деплоим в кубер".
И наконец глава, которая практически оправдала эту книгу! Глава 13 - refactoring to microservices. Почти в конце книге находится фраза, которая могла бы поменять все мое отношение к этому произведению, если бы она была в начале. Фраза, которая даже не удостоилась фирменной рамочки, как максимально важная мысль!
> You should first try simpler solutions. If, and only if, you still have software delivery problems should you then migrate to the microservice architecture.
Тысячу раз, да! Во-первых, ни одно техническое или организационное решение не имеет смысла, вне контекста проблемы! Во-вторых, любое решение — это компромисс (trade-off). При чем компромисс не только между "здесь у нас такие-то технические свойства, а здесь сякие-то", но также между "время можно потратить на это или на то". Кто из вас с пустым беклогом, пусть первый бросит в нее камень! Между простым и быстрым решением, которое почти решит проблему и сложным и долгим, которое решит её полностью, часто правильным будет первое, а не второе.
А что касается книги, если у вас и так гора опыта и bullshit фильтр выкручен на максимум — смело читайте, не повредит. Листинги можно пропускать. Если вы только знакомитесь с миром микросервисов, начните лучше с Фаулера, а затем переходите к его гайду.
🔥1
The Calculus of Service Availability
#shark_whitepaper
Сегодняшняя красивая большая пдфка формально не является вайтпейпером, т.к. выпущена не университетом, особо ничего нового не изучает и написана не в две колонки. Тем не менее, я не могу пропустить публикации инженеров гугла (когда рано или поздно их нахожу...), т.к. во-первых, питаю слабость ко всем этим SRE штукам, а во-вторых, емкие, но при этом содержательные тексты — большая редкость.
Итак, в работе кратко рассказывает, чем вообще живут SRE, и начинается все с простой математики availability:
Availability = MTTF / (MTTF + MTTR)
Где:
Availability — доступность. Какой процент времени система может корректно делать свою работу (обрабатывать запросы, перекладывать сообщения, и т.д.)
MTTF (Mean time to failure) — среднее время до отказа. Обратная величина от частоты сбоев.
MTTR (Mean time to repair) — среднее время до исправления. Здесь имеется ввиду время, через которое система придет в свои изначальное корректное состояние. Т.е. недостаточно придумать, как починить, нужно еще и применить решение.
Главная фишка этой математики в том, что из нее можно делать довольно очевидные выводы. Как повысить доступность? Смотрим на уравнение, и видим, что путей всего два:
1. Увеличить числитель, т.е. увеличить среднее время между отказами (MTTF). Делать это можно при помощи более обширного тестирования, более аккуратного деплоя (В рамках rollout policy, если такая есть, к примеру) или уменьшением скоупа отказа: географическая изоляция отказов, шардирование, graceful degradation и т.д.
2. Уменьшить знаменатель, т.е. сократить время на обнаружение и устранение проблемы (MTTR). Как говориться, быстро поднятое упавшим не считается. Здесь помогает настройка мониторинга и алертинга, интеллектуальные системы восстановления и развертывания, а также, что не менее важно, обучение сотрудников и chaos engineering.
Вторая интересная мысль из статьи — доступность сервиса не может быть больше общей доступности всех зависимостей. Если ваша БД лежит 53 минуты в течение года (99.99%), то даже при вашей 100% доступности, 53 минуты в течение года вы тоже будете не работать. Отсюда следствие: доступность зависимостей должна быть больше, чем ваша. Иначе, математика не сходится.
В конце также приводится длиннющий список разных способов повышения доступности. Очень рекомендую почитать всем, но если вы больше по хардкору или не нашли того что искали, то тут бесспорным победителем по полноте и понятности информации будут аж три книги по SRE от гугла сразу. Я советую читать справа налево (снизу вверх, если вы с мобилки).
Ну и самое главное. Как гугл решает свои проблемы — это бесспорно интересно, но может не иметь вообще никакого отношения к вашему продукту.
#shark_whitepaper
Сегодняшняя красивая большая пдфка формально не является вайтпейпером, т.к. выпущена не университетом, особо ничего нового не изучает и написана не в две колонки. Тем не менее, я не могу пропустить публикации инженеров гугла (когда рано или поздно их нахожу...), т.к. во-первых, питаю слабость ко всем этим SRE штукам, а во-вторых, емкие, но при этом содержательные тексты — большая редкость.
Итак, в работе кратко рассказывает, чем вообще живут SRE, и начинается все с простой математики availability:
Availability = MTTF / (MTTF + MTTR)
Где:
Availability — доступность. Какой процент времени система может корректно делать свою работу (обрабатывать запросы, перекладывать сообщения, и т.д.)
MTTF (Mean time to failure) — среднее время до отказа. Обратная величина от частоты сбоев.
MTTR (Mean time to repair) — среднее время до исправления. Здесь имеется ввиду время, через которое система придет в свои изначальное корректное состояние. Т.е. недостаточно придумать, как починить, нужно еще и применить решение.
Главная фишка этой математики в том, что из нее можно делать довольно очевидные выводы. Как повысить доступность? Смотрим на уравнение, и видим, что путей всего два:
1. Увеличить числитель, т.е. увеличить среднее время между отказами (MTTF). Делать это можно при помощи более обширного тестирования, более аккуратного деплоя (В рамках rollout policy, если такая есть, к примеру) или уменьшением скоупа отказа: географическая изоляция отказов, шардирование, graceful degradation и т.д.
2. Уменьшить знаменатель, т.е. сократить время на обнаружение и устранение проблемы (MTTR). Как говориться, быстро поднятое упавшим не считается. Здесь помогает настройка мониторинга и алертинга, интеллектуальные системы восстановления и развертывания, а также, что не менее важно, обучение сотрудников и chaos engineering.
Вторая интересная мысль из статьи — доступность сервиса не может быть больше общей доступности всех зависимостей. Если ваша БД лежит 53 минуты в течение года (99.99%), то даже при вашей 100% доступности, 53 минуты в течение года вы тоже будете не работать. Отсюда следствие: доступность зависимостей должна быть больше, чем ваша. Иначе, математика не сходится.
В конце также приводится длиннющий список разных способов повышения доступности. Очень рекомендую почитать всем, но если вы больше по хардкору или не нашли того что искали, то тут бесспорным победителем по полноте и понятности информации будут аж три книги по SRE от гугла сразу. Я советую читать справа налево (снизу вверх, если вы с мобилки).
Ну и самое главное. Как гугл решает свои проблемы — это бесспорно интересно, но может не иметь вообще никакого отношения к вашему продукту.
queue.acm.org
The Calculus of Service Availability - ACM Queue
Most services offered by Google aim to offer 99.99 percent (sometimes referred to as the "four 9s") availability to users. Some services contractually commit to a lower figure externally but set a 99.99 percent target internally. This more stringent target…
👍1🔥1
История CAP теоремы (1/6)
#shark_whitepaper
Буквально вчера меня триггернуло на фразу "CAP теорема — это миф" от интервьювера. В этом посте мы поговорим о том, как вообще эта теорема появилась на свет, что она значит, и немного затронем важность ограничений, при чтении любых работ по Computer Science. Тема очень обширная, поэтому весь рассказ растянется не только на несколько постов, но и на несколько дней.
Началось все в 2000 году, когда Eric Brewer (ныне — VP of infrastructure в гугле) выступил вот с этой презентацией на кейноуте симпозиума по принципам распределенных систем (PODC). Это большая крутая конференция про все распределенное, которая проходит ежегодно уже почти 40 лет. К моменту этого выступления, мир уже оперировал аббревиатурой BASE на равне с ACID, но вот фундаментальный трейд-офф между C — Consistency, A — Availability и P — partition tolerance был объявлен именно здесь (как минимум, так обычно считается в литературе).
В изначальной постановке трейд-офф звучит как "Consistency, Availability, Partition Tolerance. You can have at most two of these properties for any shared-data system". В этой же презентации приводятся примеры всех трех видов систем. В качестве CA систем приводятся Single-site databases и LDAP. Это важное замечание, так как через какое-то время, различные работы придут к выводу, что разделить CA и CP системы довольно сложно. Хотя бы потому что кратковременное отсутствие сети можно моделировать через отсутствие availability и наоборот (Такого мнения спустя 12 лет придерживается как сам автора, так и спустя 10 лет не только автор).
Вторая важная вещь, которая озвучивается в кейноуте — это DQ principle. Вводится он следующим образом:
Data/query * Queries/sec = constant = DQ
Количество данных, получаемых в одном запросе помноженное на количество запросов в секунду является константной величиной для заданной ноды, с заданными версиями операционной системы и версией программы.
Данный принцип утверждает, что в рамках работающей системы нельзя одновременно повысить и качество данных (data/query) и количество обрабатываемых запросов (queries/second). Как минимум без изменения программы / ос / сервера. Забавно, что этот трейдофф consistency/throughput/latency будет через десяток лет рассматриваться уже другими учеными, но об этом мы еще поговорим.
Но вернемся к CAP. В презентации утверждение про "возьми 2 из 3" формулируется как теорема, что фактически неверно. Теорема должна иметь доказательство, т.е. правильнее это было бы назвать другим словом, например принцип CAP или гипотеза CAP, как это делают многие последующие работы.
#shark_whitepaper
Буквально вчера меня триггернуло на фразу "CAP теорема — это миф" от интервьювера. В этом посте мы поговорим о том, как вообще эта теорема появилась на свет, что она значит, и немного затронем важность ограничений, при чтении любых работ по Computer Science. Тема очень обширная, поэтому весь рассказ растянется не только на несколько постов, но и на несколько дней.
Началось все в 2000 году, когда Eric Brewer (ныне — VP of infrastructure в гугле) выступил вот с этой презентацией на кейноуте симпозиума по принципам распределенных систем (PODC). Это большая крутая конференция про все распределенное, которая проходит ежегодно уже почти 40 лет. К моменту этого выступления, мир уже оперировал аббревиатурой BASE на равне с ACID, но вот фундаментальный трейд-офф между C — Consistency, A — Availability и P — partition tolerance был объявлен именно здесь (как минимум, так обычно считается в литературе).
В изначальной постановке трейд-офф звучит как "Consistency, Availability, Partition Tolerance. You can have at most two of these properties for any shared-data system". В этой же презентации приводятся примеры всех трех видов систем. В качестве CA систем приводятся Single-site databases и LDAP. Это важное замечание, так как через какое-то время, различные работы придут к выводу, что разделить CA и CP системы довольно сложно. Хотя бы потому что кратковременное отсутствие сети можно моделировать через отсутствие availability и наоборот (Такого мнения спустя 12 лет придерживается как сам автора, так и спустя 10 лет не только автор).
Вторая важная вещь, которая озвучивается в кейноуте — это DQ principle. Вводится он следующим образом:
Data/query * Queries/sec = constant = DQ
Количество данных, получаемых в одном запросе помноженное на количество запросов в секунду является константной величиной для заданной ноды, с заданными версиями операционной системы и версией программы.
Data/query— это сколько корректных данных возвращается из одного запроса,
queries/second— это производительность ака throughput. Здесь надо оговориться, что речь идет про очень большие и распределенные системы, а сам кейноут должен нести практически смысл. В реальных системах часть данных может быть уже внутри системы, но еще не реплецирована на необходимое количество нод, т.е. существует часть данных, которые уже внутри системы, но еще недоступны. Именно поэтому понятие "количество корректных данных" (data/query) имеет значимый смысл.
Данный принцип утверждает, что в рамках работающей системы нельзя одновременно повысить и качество данных (data/query) и количество обрабатываемых запросов (queries/second). Как минимум без изменения программы / ос / сервера. Забавно, что этот трейдофф consistency/throughput/latency будет через десяток лет рассматриваться уже другими учеными, но об этом мы еще поговорим.
Но вернемся к CAP. В презентации утверждение про "возьми 2 из 3" формулируется как теорема, что фактически неверно. Теорема должна иметь доказательство, т.е. правильнее это было бы назвать другим словом, например принцип CAP или гипотеза CAP, как это делают многие последующие работы.
🔥2👍1
История CAP теоремы (2/6)
Когда же принцип CAP стал теоремой? Это произошло в 2002 году в вайтпейпере под авторством Seth Gilbert и Nancy Lynch. Я очень советую почитать сам вайтпейпер, т.к. доказательство элементарное в рамках тех ограничений, которые задаются для рассматриваемой системы. Если что, то же самое доказательство есть с картинками, тут уж точно все станет понятно (Нет, серьезно, универские доказательства из матана в десятки раз более замудренные, чем то что написано в работе по CAP)
Как известно, когда дело доходил до формальных доказательств, нельзя просто так брать и рассматривать все множество доступных вычислений. Нужно оперировать некими определениями, ограничениями и моделями. В частности в этой работе вводятся следующие ограничения:
- Рассматривается асинхронная модель взаимодействия. Асинхронная это значит 2 вещи. Во-первых, невозможно отличить отказ системы от "тормозов". Во-вторых, любое сообщение может доставляться и обрабатываться неопределенное, но не бесконечное время. В целом первое следует из второго.
- Consistency рассматривается, как атомарность или линеаризуемость. Это значит, что система для внешнего наблюдателя всегда выглядит так, словно она состоит из одного сервера. Более формально, в линеаризуемой системе всегда существует линейная упорядоченность (total order) всех операций относительно единственно-верных часов.
- Partition Toleranse вернее partition (разделение сети) рассматривается как бессрочное разделение.
- Availability. Здесь формулируется как "любая не вышедшая из строя нода должна возвращать корректный результат".
Сама формулировка теоремы следующая:
- Availability
- Atomic consistency
in all fair executions (including those in which messages are lost)
Обратите внимание, что уже на уровне формулировки не учитывается возможность существования CA систем. Формулировка вообще ничего не говорит про "выбери 2 из 3". После этой теоремы, идет еще следствие из нее, в котором говорится, что условие недостижимо даже при отсутствии пропавших сообщений.
Приблизительно здесь заканчивается первая половина всей работы! Во второй рассматриваются менее строгие системы, а именно системы, оперирующие в partially synchronous модели. Это модель, в которой у каждой ноды есть свои часы (не синхронизированные между друг другом). Так вот, в такой системе все еще невозможность обеспечить одновременно availability и atomic consistency в общем случае, но это становится возможно если не потерять ни одного сообщения.
Давайте перейдем теперь к самому интересному... Что же не так с CAP? Ответ выходит прямиком из ограничений, необходимых для доказательства теоремы.
Во-первых, консистентность как линеаризуемость. Это очень жесткое требование, и большинство современных хранилищ данных, в принципе не могут функционировать линеаризуемо.
Во-вторых, разделение сети рассматривается как бессрочное. Большинство современных систем надеются на то что связь когда-нибудь восстановится. Таким образом ограничение теоремы про бесконечные промежутки разделения сети имеет мало общего с реальным миром.
Наконец, в-третьих, доступность. В ограничениях теоремы указывается, что система доступна, когда любая работающая нода отвечает корректно. В реальном мире обычно достаточно, когда какое-то подмножество нод возвращает корректный результат.
Получается, что главная проблема CAP теоремы в целом заключается в том, что модель и ограничения, в рамках которых она рассматривается, практически неприменима для реального мира. Тем не менее эта работа все еще корректна и верна! Неприменима вовсе не то же самое, что неверна. С другой стороны, раз уж она не применима практически всегда, почему вендоры хранилищ данных так любят говорить CP у них или AP? Вот это уже вопрос, на который у меня нет ответа.
На этом пока что все. В следующих постах мы рассмотрим, что нового появилось рядом с CAP за следующие ~ 15 лет после её выхода.
Когда же принцип CAP стал теоремой? Это произошло в 2002 году в вайтпейпере под авторством Seth Gilbert и Nancy Lynch. Я очень советую почитать сам вайтпейпер, т.к. доказательство элементарное в рамках тех ограничений, которые задаются для рассматриваемой системы. Если что, то же самое доказательство есть с картинками, тут уж точно все станет понятно (Нет, серьезно, универские доказательства из матана в десятки раз более замудренные, чем то что написано в работе по CAP)
Как известно, когда дело доходил до формальных доказательств, нельзя просто так брать и рассматривать все множество доступных вычислений. Нужно оперировать некими определениями, ограничениями и моделями. В частности в этой работе вводятся следующие ограничения:
- Рассматривается асинхронная модель взаимодействия. Асинхронная это значит 2 вещи. Во-первых, невозможно отличить отказ системы от "тормозов". Во-вторых, любое сообщение может доставляться и обрабатываться неопределенное, но не бесконечное время. В целом первое следует из второго.
- Consistency рассматривается, как атомарность или линеаризуемость. Это значит, что система для внешнего наблюдателя всегда выглядит так, словно она состоит из одного сервера. Более формально, в линеаризуемой системе всегда существует линейная упорядоченность (total order) всех операций относительно единственно-верных часов.
- Partition Toleranse вернее partition (разделение сети) рассматривается как бессрочное разделение.
- Availability. Здесь формулируется как "любая не вышедшая из строя нода должна возвращать корректный результат".
Сама формулировка теоремы следующая:
> It is impossible in the asynchronous network model to implement a read/write data object that guarantees the following properties: - Availability
- Atomic consistency
in all fair executions (including those in which messages are lost)
Обратите внимание, что уже на уровне формулировки не учитывается возможность существования CA систем. Формулировка вообще ничего не говорит про "выбери 2 из 3". После этой теоремы, идет еще следствие из нее, в котором говорится, что условие недостижимо даже при отсутствии пропавших сообщений.
Приблизительно здесь заканчивается первая половина всей работы! Во второй рассматриваются менее строгие системы, а именно системы, оперирующие в partially synchronous модели. Это модель, в которой у каждой ноды есть свои часы (не синхронизированные между друг другом). Так вот, в такой системе все еще невозможность обеспечить одновременно availability и atomic consistency в общем случае, но это становится возможно если не потерять ни одного сообщения.
Давайте перейдем теперь к самому интересному... Что же не так с CAP? Ответ выходит прямиком из ограничений, необходимых для доказательства теоремы.
Во-первых, консистентность как линеаризуемость. Это очень жесткое требование, и большинство современных хранилищ данных, в принципе не могут функционировать линеаризуемо.
Во-вторых, разделение сети рассматривается как бессрочное. Большинство современных систем надеются на то что связь когда-нибудь восстановится. Таким образом ограничение теоремы про бесконечные промежутки разделения сети имеет мало общего с реальным миром.
Наконец, в-третьих, доступность. В ограничениях теоремы указывается, что система доступна, когда любая работающая нода отвечает корректно. В реальном мире обычно достаточно, когда какое-то подмножество нод возвращает корректный результат.
Получается, что главная проблема CAP теоремы в целом заключается в том, что модель и ограничения, в рамках которых она рассматривается, практически неприменима для реального мира. Тем не менее эта работа все еще корректна и верна! Неприменима вовсе не то же самое, что неверна. С другой стороны, раз уж она не применима практически всегда, почему вендоры хранилищ данных так любят говорить CP у них или AP? Вот это уже вопрос, на который у меня нет ответа.
На этом пока что все. В следующих постах мы рассмотрим, что нового появилось рядом с CAP за следующие ~ 15 лет после её выхода.
🔥1
История CAP теоремы (3/6)
Продолжаем наш рассказ. Следующая важная веха вокруг CAP теоремы случилось аж спустя 12 лет с момента первой презентации. Автором этого огромного поста снова стал Eric Brewer. Забавно, что факт доказательства теоремы им практически полностью игнорируется. Но с другой стороны, оно и понятно, потому что у CAP есть 2 жизни. Первая — это формальные доказательства, задача которых задать верхнюю и нижнюю границу возможного. А второе — это реальные системы, в которых существуют реальные трейдоффы. Им и посвящен этот пост.
Статья начиная с разъяснений, почему нельзя просто так брать определение из теоремы и кричать, что тут у вас AP, а тут CP — настоящие системы слишком сложны.
Во-первых, partition tolerance предполагает, что система знает о разделении. Это, к сожалению, не всегда так. Сеть может разрываться в неожиданных местах, так что для одной части системы некоторая нода недоступна, а для другой части доступна. Более того, независимые части системы в целом могут продолжать работу даже при разделении сети. Возьмем, например, сервис такси в Северной Америке и Европе. Всегда ли необходимо наличие связи между ними? Скорее всего нет, так как никто не будет вызывать такси из Вашингтона в Амстердам. При этом эти 2 части могут продолжать обрабатывать запросы, даже когда сети между ними нет.
Во-вторых, разделение сети — далеко не единственная возможная проблема. Система вполне может потерять и доступность, и консистентность после неудачного релиза. А для некоторых систем недоступностью будет слишком высокие задержки, хотя запросы все еще будут обрабатываться (например, биржевые роботы). Строго говоря, консистентность и доступность — это не бинарные понятия. Является ли доступной система, которая успешно возвращает 99% данных, а 1% произвольно дропает? С точки зрения формальных определений — нет. С точки зрения стриминг-портала, вполне себе рабочий вариант.
В-третих, чему посвящена основная часть статьи, отказ от консистентности в пользу доступности часто недостижим. Лучше что можно сделать — это отложить момент наступления консистентности. Никто не любит, когда их данные теряются. Как быть?
Для начала, было бы хорошо обнаруживать недоступность между компонентами. Здесь человечество изобрело уже множество подходов от синхронных health чеков с таймаутами (напомню, что формально CAP рассматривается в асинхронной системе. Синхронных операций в такой системе нет) до алгоритмов консенсуса. Следующие шаг — перейти в явный режим работы при разделении сети, а при восстановлении, собственно, провести компенсации.
Звучит хорошо, на практике все не так просто. Чтобы корректно восстановить консистентность, после возобновления сетевой доступности, нужно знать как минимум все инварианты системы. Инварианты — это условия, которые должна оставаться верными в любой ситуации. Баланс не может быть меньше нуля, у пользователя может быть ровно 1 аккаунт, по одному закажу должен быть ровно один платеж и прочие-прочие-прочие ситуации. Знать и учитывать все это сложно. Еще сложнее, уметь корректно разрешать конфликтные ситуации. Пусть за время конфликта один и тот же заказ сначала отменился, а чуть попозже взял и оплатился. Что делать? Поди его там разбери, что хотел сделать пользовать!
Продолжаем наш рассказ. Следующая важная веха вокруг CAP теоремы случилось аж спустя 12 лет с момента первой презентации. Автором этого огромного поста снова стал Eric Brewer. Забавно, что факт доказательства теоремы им практически полностью игнорируется. Но с другой стороны, оно и понятно, потому что у CAP есть 2 жизни. Первая — это формальные доказательства, задача которых задать верхнюю и нижнюю границу возможного. А второе — это реальные системы, в которых существуют реальные трейдоффы. Им и посвящен этот пост.
Статья начиная с разъяснений, почему нельзя просто так брать определение из теоремы и кричать, что тут у вас AP, а тут CP — настоящие системы слишком сложны.
Во-первых, partition tolerance предполагает, что система знает о разделении. Это, к сожалению, не всегда так. Сеть может разрываться в неожиданных местах, так что для одной части системы некоторая нода недоступна, а для другой части доступна. Более того, независимые части системы в целом могут продолжать работу даже при разделении сети. Возьмем, например, сервис такси в Северной Америке и Европе. Всегда ли необходимо наличие связи между ними? Скорее всего нет, так как никто не будет вызывать такси из Вашингтона в Амстердам. При этом эти 2 части могут продолжать обрабатывать запросы, даже когда сети между ними нет.
Во-вторых, разделение сети — далеко не единственная возможная проблема. Система вполне может потерять и доступность, и консистентность после неудачного релиза. А для некоторых систем недоступностью будет слишком высокие задержки, хотя запросы все еще будут обрабатываться (например, биржевые роботы). Строго говоря, консистентность и доступность — это не бинарные понятия. Является ли доступной система, которая успешно возвращает 99% данных, а 1% произвольно дропает? С точки зрения формальных определений — нет. С точки зрения стриминг-портала, вполне себе рабочий вариант.
В-третих, чему посвящена основная часть статьи, отказ от консистентности в пользу доступности часто недостижим. Лучше что можно сделать — это отложить момент наступления консистентности. Никто не любит, когда их данные теряются. Как быть?
Для начала, было бы хорошо обнаруживать недоступность между компонентами. Здесь человечество изобрело уже множество подходов от синхронных health чеков с таймаутами (напомню, что формально CAP рассматривается в асинхронной системе. Синхронных операций в такой системе нет) до алгоритмов консенсуса. Следующие шаг — перейти в явный режим работы при разделении сети, а при восстановлении, собственно, провести компенсации.
Звучит хорошо, на практике все не так просто. Чтобы корректно восстановить консистентность, после возобновления сетевой доступности, нужно знать как минимум все инварианты системы. Инварианты — это условия, которые должна оставаться верными в любой ситуации. Баланс не может быть меньше нуля, у пользователя может быть ровно 1 аккаунт, по одному закажу должен быть ровно один платеж и прочие-прочие-прочие ситуации. Знать и учитывать все это сложно. Еще сложнее, уметь корректно разрешать конфликтные ситуации. Пусть за время конфликта один и тот же заказ сначала отменился, а чуть попозже взял и оплатился. Что делать? Поди его там разбери, что хотел сделать пользовать!
🔥1
История CAP теоремы (4/6)
Поэтому предлагается решать такие конфликты аж четырьмя способами:
1. После обнаружения разделения сети, не позволять делать часть операций. Дубовый и прямолинейный способ, единственное что, пользователи страдают, а также определить, какие операции опасные, а какие нет для конфликтов восстановления — задача непростая.
2. Собирать отладочную информацию. Например, собирать version vectors, а после восстановления, объединять их в консистентное состояние. В теории хорошо, на практике зависит от того, как долго длится разъединение, и какие операции происходят.
3. Использовать коммутативные и иммутабельные операции, а еще лучше даже conflict-free replicated data types. Проблема в том что не все можно реализовать на CRDT. Особенно тяжело для них выполнять инварианты. Сложить несколько плюсов и минусов баланса — просто. Сложить две разные корзины товаров, как множества тоже просто. Сделать так, чтобы ни одна операция не вывела баланс за нуль — сложно.
4. Вести аудит операций, а затем запускать компенсирующую логику. Подход похож на version vectors, но может быть реализован самыми неожиданными способами. Например, банк может взимать плату за овердрафт, в качестве компенсации за то что баланс уменьшился ниже нуля, если сможет доказать, что это пользовать сам одновременно снял деньги в банкомате и перевел на другой счет.
Как обычно, в реальном мире простых решений нет. Формальные доказательства не спасают, а только заставляются задумываться. Но история CAP теоремы все еще не закончена...
Поэтому предлагается решать такие конфликты аж четырьмя способами:
1. После обнаружения разделения сети, не позволять делать часть операций. Дубовый и прямолинейный способ, единственное что, пользователи страдают, а также определить, какие операции опасные, а какие нет для конфликтов восстановления — задача непростая.
2. Собирать отладочную информацию. Например, собирать version vectors, а после восстановления, объединять их в консистентное состояние. В теории хорошо, на практике зависит от того, как долго длится разъединение, и какие операции происходят.
3. Использовать коммутативные и иммутабельные операции, а еще лучше даже conflict-free replicated data types. Проблема в том что не все можно реализовать на CRDT. Особенно тяжело для них выполнять инварианты. Сложить несколько плюсов и минусов баланса — просто. Сложить две разные корзины товаров, как множества тоже просто. Сделать так, чтобы ни одна операция не вывела баланс за нуль — сложно.
4. Вести аудит операций, а затем запускать компенсирующую логику. Подход похож на version vectors, но может быть реализован самыми неожиданными способами. Например, банк может взимать плату за овердрафт, в качестве компенсации за то что баланс уменьшился ниже нуля, если сможет доказать, что это пользовать сам одновременно снял деньги в банкомате и перевел на другой счет.
Как обычно, в реальном мире простых решений нет. Формальные доказательства не спасают, а только заставляются задумываться. Но история CAP теоремы все еще не закончена...
🔥2
История CAP теоремы (5/6)
Следующая важная работа для истории CAP это "утверждение" PACELC (произносится pass-elk) под авторством Daniel J. Abadi. Иногда ее называют "теорема PACELC", что совершенно неверно, т.к. сама работа не содержит формальных доказательств, это скорее рассуждения и логические выводы. Исторически она вышла на пару месяцев раньше, чем 12-лет-спустя, но статьи друг от друга не зависят и представляют разные элементы одних и тех же трейдоффов.
Формулировка следующая:
Если в 12-лет-спустя говорится, что от консистентности нельзя в принципе оказаться, то тут автор предлагает задуматься, какие трейдоффы нужно делать еще до того, как разделение сети произойдет. А трейдоффы здесь между консистеностью и задержками (latency). Забавно что в самой-самой первой презентации от Eric Brewer (о ней см. пост #1) было аналогичное утверждение в виде DQ принципа. Нельзя одновременно улучшить и консистентность и производительность vs нельзя одновременно улучшить консистеность и latency.
Рассуждения строятся следующим образом. Если система highly available, то потеря ноды с данными не должна автоматически приводить к потере данных. Значит, данные нужно реплицировать. Рассмотрим все возможные методы репликации и посмотрим, какие в них вылезают трейдоффы.
Вариант 1: Данные реплицируются во все n реплик одновременно. Если вся репликация синхронная — любой отказ это недоступность, а мы строим "highly available". Если отказ одной реплики не проблема, значит автоматически должен существовать алгоритм репликации, который включает восстановление как минимум корректного порядка сообщений. Значит есть какая-то лишняя работа == есть задержки. Нужно выбирать делать более консистентный и медленный алгоритм или наоборот.
Вариант 2: Данные направляются в определенные ноды, а лишь затем реплицируются. Например write master - read slave репликация. По этому пути есть 2 дороги:
- 2.1: Синхронная репликация. Общая задержка равна времени на самый длительный запрос в лучшем случае. В худшем и того больше. Нужно выбирать на сколько нод реплицировать, т.е. прямо сразу приходим к consistency vs latency.
- 2.2: Асинхронная репликация. Здесь могут быть такие проблемы с консистентность, как Read Your Writes, Write Follow Reads и прочие интересные особенности (см. правый кусок дерева здесь). Их можно так или иначе обойти, но об этом надо думать, принимать решение, и писать исполняемый код, а значит трейдвофф между задержками и консистентностью тоже есть.
Вариант 3: Данные направляются в произвольную ноду (не прямо произвольную, конечно, а например в любую из какого-то кворума). В сущности что здесь, что в варианте 2 проблемы и решения совершенно одинаковые, так что снова есть тредофф latency vs consistency.
С подходом PACELC система может классифицироваться 4 буквами. В качестве примера автор говорит, что MongoDB это PA/EC. При наличии партиций (PA) она остается доступной, т.к. отделенная от остального кластера нода продолжает писать в rollback директорию. При этом без партиций (EC) гарантируется консистеность в первую очередь... Как минимум в соответствии с документацией. Кому интересно, в статье еще рассматривается VoltDB/H-Store (PC/EC), PNUTS (PC/EL) и DynamoDB, Cassandra, Riak (PA/EL). Хотя "рассматривается" это сильно сказано, там по одному параграфу.
А еще хорошие новости! Мне осталась буквально 1 работа и мы закончим с CAPом... пока что.
Следующая важная работа для истории CAP это "утверждение" PACELC (произносится pass-elk) под авторством Daniel J. Abadi. Иногда ее называют "теорема PACELC", что совершенно неверно, т.к. сама работа не содержит формальных доказательств, это скорее рассуждения и логические выводы. Исторически она вышла на пару месяцев раньше, чем 12-лет-спустя, но статьи друг от друга не зависят и представляют разные элементы одних и тех же трейдоффов.
Формулировка следующая:
PACELC: if there is a partition (P), how does the system trade off availability and consistency (A and C); else (E), when the system is running normally in the absence of partitions, how does the system trade off latency (L) and consistency (C)?
Если в 12-лет-спустя говорится, что от консистентности нельзя в принципе оказаться, то тут автор предлагает задуматься, какие трейдоффы нужно делать еще до того, как разделение сети произойдет. А трейдоффы здесь между консистеностью и задержками (latency). Забавно что в самой-самой первой презентации от Eric Brewer (о ней см. пост #1) было аналогичное утверждение в виде DQ принципа. Нельзя одновременно улучшить и консистентность и производительность vs нельзя одновременно улучшить консистеность и latency.
Рассуждения строятся следующим образом. Если система highly available, то потеря ноды с данными не должна автоматически приводить к потере данных. Значит, данные нужно реплицировать. Рассмотрим все возможные методы репликации и посмотрим, какие в них вылезают трейдоффы.
Вариант 1: Данные реплицируются во все n реплик одновременно. Если вся репликация синхронная — любой отказ это недоступность, а мы строим "highly available". Если отказ одной реплики не проблема, значит автоматически должен существовать алгоритм репликации, который включает восстановление как минимум корректного порядка сообщений. Значит есть какая-то лишняя работа == есть задержки. Нужно выбирать делать более консистентный и медленный алгоритм или наоборот.
Вариант 2: Данные направляются в определенные ноды, а лишь затем реплицируются. Например write master - read slave репликация. По этому пути есть 2 дороги:
- 2.1: Синхронная репликация. Общая задержка равна времени на самый длительный запрос в лучшем случае. В худшем и того больше. Нужно выбирать на сколько нод реплицировать, т.е. прямо сразу приходим к consistency vs latency.
- 2.2: Асинхронная репликация. Здесь могут быть такие проблемы с консистентность, как Read Your Writes, Write Follow Reads и прочие интересные особенности (см. правый кусок дерева здесь). Их можно так или иначе обойти, но об этом надо думать, принимать решение, и писать исполняемый код, а значит трейдвофф между задержками и консистентностью тоже есть.
Вариант 3: Данные направляются в произвольную ноду (не прямо произвольную, конечно, а например в любую из какого-то кворума). В сущности что здесь, что в варианте 2 проблемы и решения совершенно одинаковые, так что снова есть тредофф latency vs consistency.
С подходом PACELC система может классифицироваться 4 буквами. В качестве примера автор говорит, что MongoDB это PA/EC. При наличии партиций (PA) она остается доступной, т.к. отделенная от остального кластера нода продолжает писать в rollback директорию. При этом без партиций (EC) гарантируется консистеность в первую очередь... Как минимум в соответствии с документацией. Кому интересно, в статье еще рассматривается VoltDB/H-Store (PC/EC), PNUTS (PC/EL) и DynamoDB, Cassandra, Riak (PA/EL). Хотя "рассматривается" это сильно сказано, там по одному параграфу.
А еще хорошие новости! Мне осталась буквально 1 работа и мы закончим с CAPом... пока что.
🔥1
История CAP теоремы (6/6)
Последняя работа, о которой я бы хотел упомянуть, это критика CAP от Martin Kleppman, того самого автора книжки с кабанчиком.
Первая часть посвящена, собственно, разбору CAP из 3 частей. Что не так, что не понятно, где термины даются не четко, и какие из этого всего вытекают проблемы. К концу даже доказывается ряд теорем, очень похожих на CAP, но без двусмысленных формулировок. Эта часть на 100% формальная, и мы её пропустим, но сама терминология и доказательство поразительно лаконичны. Рекомендую почитать, если вам нравится такой формат.
Вторая часть рассказывает про фреймворк delay-sensitivity. Идея заключается в том, что в настоящий момент существует пропасть между теоретическими изысканиями, такими как формальное доказательство CAP теоремы и практическими системами. Например, в современном мире слишком высокая задержка (latency) приравнивается к недоступности сервиса (SLA/O, вот это все). Значит нужно построить такую модель терминов, которая помогла бы разговаривать на одном языке исследователям и разработчикам, при этом покрывала бы реальные кейсы.
Модель выстраивается в 2 этапа. Сначала задаются теоретические нижние границы времени выполнения операций чтения и записи для разных уровней консистентности в зависимости от сетевых задержек (обозначаются здесь через
- linearizability — и чтение, и запись
- sequential consistency — либо чтение, либо запись
- casual consistency — обе операции за
Следует помнить, что наличие формального доказательства вовсе не обозначает применимость в реальном мире. Например, оказывается что casually consistent хранилище может и читать и писать за константу. Вот только для этого нужно передавать еще мешок данных, по которым можно определить эту самую casualty, что в реальных системах нецелесообразно. Поэтому, в частности, в реальном мире существуют более слабые гарантии, например eventually consistent системы.
А дальше, собственно, идет терминология delay-sensitivity фреймворка:
- Availability следует считать эмпирической величиной, равной проценту успешных запросов от количества общих в период времени. Чуть подробнее про эмпирическое значение availability я писал тут.
- Delay-sensitive — это свойство алгоритма, обозначающее, что ему нужно ждать задержку
- Network Faults. Должны включать в себя не только полный network partition, но так же и периодические потери пакетов (ака "сеть моргнула") и внезапное превышение средних задержек. Все три показателя важны для реальной системы.
- Fault Tolerance — следует использовать вместо понятия partition tolerance. Алгоритм должен описывать какие ошибки он может пережить (например, потерю менее половины нод), а также что происходит, если лимит ошибок превышен.
- Consistency должен обозначать одну из известных моделей. Слово strong consistency не имеет смысла и лишь усложняет понимание.
Приживется ли терминология, покажет лишь время. Работа молодая, ей едва ли стукнуло 6 лет!
А на этом наш сказ про CAP закончился. Осталось только подвести итог:
- Под словом CAP понимают две вещи. Первая — формально доказанное утверждение, которое практически не имеет применений в реальности. Вторая — набор суждений про вечный трейдофф consistency/availability/latency/throughput/что-угодно-ещё.
- Разделение сети (partition tolerance) — это возможная, но далеко не единственная ошибка, которая может возникнуть в системе. В реальном мире нужно защищаться от всего.
- Доступность (Availability) в литературе и в реальном мире — две в сущности независимые вещи. В работах это "возможность получить результат", в мире — эмпирическая метрика.
- Даже без явных ошибок, в распределенной системе есть трейдоффы, а все эти консистентности и доступности — не бинарные величины, а точки на спектре.
Последняя работа, о которой я бы хотел упомянуть, это критика CAP от Martin Kleppman, того самого автора книжки с кабанчиком.
Первая часть посвящена, собственно, разбору CAP из 3 частей. Что не так, что не понятно, где термины даются не четко, и какие из этого всего вытекают проблемы. К концу даже доказывается ряд теорем, очень похожих на CAP, но без двусмысленных формулировок. Эта часть на 100% формальная, и мы её пропустим, но сама терминология и доказательство поразительно лаконичны. Рекомендую почитать, если вам нравится такой формат.
Вторая часть рассказывает про фреймворк delay-sensitivity. Идея заключается в том, что в настоящий момент существует пропасть между теоретическими изысканиями, такими как формальное доказательство CAP теоремы и практическими системами. Например, в современном мире слишком высокая задержка (latency) приравнивается к недоступности сервиса (SLA/O, вот это все). Значит нужно построить такую модель терминов, которая помогла бы разговаривать на одном языке исследователям и разработчикам, при этом покрывала бы реальные кейсы.
Модель выстраивается в 2 этапа. Сначала задаются теоретические нижние границы времени выполнения операций чтения и записи для разных уровней консистентности в зависимости от сетевых задержек (обозначаются здесь через
d). Каждый уровень сопровождается ссылкой на доказательство.- linearizability — и чтение, и запись
O(d). Пруф.- sequential consistency — либо чтение, либо запись
O(d). Второе из двух может быть O(1). Пруф.- casual consistency — обе операции за
O(1). Пруф 1, пруф 2.Следует помнить, что наличие формального доказательства вовсе не обозначает применимость в реальном мире. Например, оказывается что casually consistent хранилище может и читать и писать за константу. Вот только для этого нужно передавать еще мешок данных, по которым можно определить эту самую casualty, что в реальных системах нецелесообразно. Поэтому, в частности, в реальном мире существуют более слабые гарантии, например eventually consistent системы.
А дальше, собственно, идет терминология delay-sensitivity фреймворка:
- Availability следует считать эмпирической величиной, равной проценту успешных запросов от количества общих в период времени. Чуть подробнее про эмпирическое значение availability я писал тут.
- Delay-sensitive — это свойство алгоритма, обозначающее, что ему нужно ждать задержку
d пока шаг выполнится. В противоположность ставиться delay-insensitive, которым ждать не нужно. Как пример — запись в мастер может сделаться сразу же, а вот репликация данных в другие ноды минимум за d. - Network Faults. Должны включать в себя не только полный network partition, но так же и периодические потери пакетов (ака "сеть моргнула") и внезапное превышение средних задержек. Все три показателя важны для реальной системы.
- Fault Tolerance — следует использовать вместо понятия partition tolerance. Алгоритм должен описывать какие ошибки он может пережить (например, потерю менее половины нод), а также что происходит, если лимит ошибок превышен.
- Consistency должен обозначать одну из известных моделей. Слово strong consistency не имеет смысла и лишь усложняет понимание.
Приживется ли терминология, покажет лишь время. Работа молодая, ей едва ли стукнуло 6 лет!
А на этом наш сказ про CAP закончился. Осталось только подвести итог:
- Под словом CAP понимают две вещи. Первая — формально доказанное утверждение, которое практически не имеет применений в реальности. Вторая — набор суждений про вечный трейдофф consistency/availability/latency/throughput/что-угодно-ещё.
- Разделение сети (partition tolerance) — это возможная, но далеко не единственная ошибка, которая может возникнуть в системе. В реальном мире нужно защищаться от всего.
- Доступность (Availability) в литературе и в реальном мире — две в сущности независимые вещи. В работах это "возможность получить результат", в мире — эмпирическая метрика.
- Даже без явных ошибок, в распределенной системе есть трейдоффы, а все эти консистентности и доступности — не бинарные величины, а точки на спектре.
🔥2
Про алгоритмы на собеседованиях
За последнюю неделю, я наткнулся аж на раз и два поста про то, как неправильно большие компании нанимают разработчиков. Истории звучат всегда как под копирку... либо «десять тысяч лет я делаю реальный софт, а меня не берут», либо «задачи непрактичные и бесполезные. Кому нужны ваши алгоритмы». Позиции кандидатов можно посочувствовать, но это скучно, поэтому время вызывать адвоката дьявола.
Начнём издалека. IT системы постоянно растут, обрабатывают все больше и больше запросов-в-секунду и петабайт-в-месяц. Каждые новые x10, а то и х5 клиентов требует рефакторингов, новых подходов, архитектуры. Создание чего-либо с нуля это дорого, долго и никаких гарантий, поэтому по возможности предпочтение отдаётся "проверенным решениям". Зачем писать свою кеш-систему, если можно взять готовую? Для чего думать над корректной асинхронностью, если уже изобрели системы обмена сообщениями?
Подход подкупает логичностью. Возьмём решение, которое у кого-то уже сработало, реализуем у себя. Затем оставим на веки вечные, до тех пор, пока оно справляется с нагрузкой / профилем / объемом данных / и т.д. Естественно все нужные нам параметры замерим. Получается и риски минимизировали, и время на разработку сократили, и еще можно хвастаться, что у нас в стеке +1 модный баззворд. Красота!
Вернёмся снова к компаниям и их собеседованиям. Вы создатель нового успешного стартапа, наняли первых пятерых разработчиков методом... разговора по душам конечно же, как же ещё, ведь вы люто ненавидите алгоритмические задачки на интервью. Проходит несколько месяцев. Теперь в компании уже 50 разработчиков. Проводить собеседования самому становится тяжело, поэтому функция оценки кандидата уходит в команды. Но вот незадача, то наймут короля токсичности, то супер-звезду, которому через полгода надоест, то сэра самозванца (не тот, который синдром, а тот который бездарен в своей профессии) Надо что-то делать...
Начинает создаваться некий формальный процесс найма, цель которого — нанимать более подходящих кандидатов. Как и в IT, этот процесс покрывается метриками от оценки кандидата до среднего времени жизни сотрудника и удовлетворённости своей работой. Появляются пулы вопросов, обязательная culture fit часть, exit-интервью, круговые ревью, в общем используются готовые решения, которые у кого-то уже сработали.
Ваш стартап стал серьёзной компанией. Теперь вы нанимаете по 50 человек в месяц, вы уже мыслите числами и метриками. При вашем текущем подходе только 60% кандидатов выходят на средний уровень производительности команды за 4 месяца. Получается остальные 40% не дотягивают! Возможно, думаете вы, проблема в том, что к нам приходят технически слабо подготовленные специалисты. Ваш Вице-Президент-По-HR советует вам посмотреть на опыт компании "условно-гугл" и давать алгоритмические задачи. Вам эта идея противна, но с ней соглашается совет директоров. Придется делать. Но мы же большая и умная компания, поэтому проведём A/B тест. 80% кандидатов поведём по старому процессу, а 20% по-новому, с алгоритмами.
И о чудо, через полгода замеров оказывается, что из тестовой когорты, которая проходила алгоритмические задачи, вышло на нужную вам производительность за 4 месяца 89% сотрудников. Это на 29% больше, чем ранее, прирост почти в два раза! Вы не верите в алгоритмы, пытаетесь еще одной A/B когорте дать упрощенные задачки, метрика падает до 63%. Следующей даёте 3 дизайн секции и 1 на программирование. Поднимается до 74%, но это не 89%. Да что же такое! Вам самому противно в душе, но цифры говорят, что алгоритмы работают, а остальные подходы не работают.
Вас ненавидят в интеренатах, поносят "не имеющие ничего общего с реальностью" алгоритмические секции. Но почему-то когда процесс найма становится другим, кандидаты нанимаются плохие. Да, ваш процесс раз в месяц отсеивает очередного создателя homebrew (если что, он извинился), да ваш HR бренд в каком-то смысле страдает... Но ведь оно работает. А работает — не трогай. Хочешь поменять — сначала измерь. Только не пытайся доказать, что с алгоритмами статистически и вправду лучше найм, не поверят!
За последнюю неделю, я наткнулся аж на раз и два поста про то, как неправильно большие компании нанимают разработчиков. Истории звучат всегда как под копирку... либо «десять тысяч лет я делаю реальный софт, а меня не берут», либо «задачи непрактичные и бесполезные. Кому нужны ваши алгоритмы». Позиции кандидатов можно посочувствовать, но это скучно, поэтому время вызывать адвоката дьявола.
Начнём издалека. IT системы постоянно растут, обрабатывают все больше и больше запросов-в-секунду и петабайт-в-месяц. Каждые новые x10, а то и х5 клиентов требует рефакторингов, новых подходов, архитектуры. Создание чего-либо с нуля это дорого, долго и никаких гарантий, поэтому по возможности предпочтение отдаётся "проверенным решениям". Зачем писать свою кеш-систему, если можно взять готовую? Для чего думать над корректной асинхронностью, если уже изобрели системы обмена сообщениями?
Подход подкупает логичностью. Возьмём решение, которое у кого-то уже сработало, реализуем у себя. Затем оставим на веки вечные, до тех пор, пока оно справляется с нагрузкой / профилем / объемом данных / и т.д. Естественно все нужные нам параметры замерим. Получается и риски минимизировали, и время на разработку сократили, и еще можно хвастаться, что у нас в стеке +1 модный баззворд. Красота!
Вернёмся снова к компаниям и их собеседованиям. Вы создатель нового успешного стартапа, наняли первых пятерых разработчиков методом... разговора по душам конечно же, как же ещё, ведь вы люто ненавидите алгоритмические задачки на интервью. Проходит несколько месяцев. Теперь в компании уже 50 разработчиков. Проводить собеседования самому становится тяжело, поэтому функция оценки кандидата уходит в команды. Но вот незадача, то наймут короля токсичности, то супер-звезду, которому через полгода надоест, то сэра самозванца (не тот, который синдром, а тот который бездарен в своей профессии) Надо что-то делать...
Начинает создаваться некий формальный процесс найма, цель которого — нанимать более подходящих кандидатов. Как и в IT, этот процесс покрывается метриками от оценки кандидата до среднего времени жизни сотрудника и удовлетворённости своей работой. Появляются пулы вопросов, обязательная culture fit часть, exit-интервью, круговые ревью, в общем используются готовые решения, которые у кого-то уже сработали.
Ваш стартап стал серьёзной компанией. Теперь вы нанимаете по 50 человек в месяц, вы уже мыслите числами и метриками. При вашем текущем подходе только 60% кандидатов выходят на средний уровень производительности команды за 4 месяца. Получается остальные 40% не дотягивают! Возможно, думаете вы, проблема в том, что к нам приходят технически слабо подготовленные специалисты. Ваш Вице-Президент-По-HR советует вам посмотреть на опыт компании "условно-гугл" и давать алгоритмические задачи. Вам эта идея противна, но с ней соглашается совет директоров. Придется делать. Но мы же большая и умная компания, поэтому проведём A/B тест. 80% кандидатов поведём по старому процессу, а 20% по-новому, с алгоритмами.
И о чудо, через полгода замеров оказывается, что из тестовой когорты, которая проходила алгоритмические задачи, вышло на нужную вам производительность за 4 месяца 89% сотрудников. Это на 29% больше, чем ранее, прирост почти в два раза! Вы не верите в алгоритмы, пытаетесь еще одной A/B когорте дать упрощенные задачки, метрика падает до 63%. Следующей даёте 3 дизайн секции и 1 на программирование. Поднимается до 74%, но это не 89%. Да что же такое! Вам самому противно в душе, но цифры говорят, что алгоритмы работают, а остальные подходы не работают.
Вас ненавидят в интеренатах, поносят "не имеющие ничего общего с реальностью" алгоритмические секции. Но почему-то когда процесс найма становится другим, кандидаты нанимаются плохие. Да, ваш процесс раз в месяц отсеивает очередного создателя homebrew (если что, он извинился), да ваш HR бренд в каком-то смысле страдает... Но ведь оно работает. А работает — не трогай. Хочешь поменять — сначала измерь. Только не пытайся доказать, что с алгоритмами статистически и вправду лучше найм, не поверят!
🔥1
Кеширование и TinyLFU
#shark_whitepaper
#shark_recommends
Работы как сегодняшняя (ссылка-клон) не позволяют делать по посту о пейперах раз в неделю, так как информации слишком много. Это исследование настолько открывает границы сознания, что его нужно перечитать несколько раз. Сначала, чтобы восхититься красотой идеи, затем чтобы понять суть.
Для начала отойдём на несколько шагов назад. Когда дело касается "оптимизации доступа", в первую очередь речь идет про техники, рассматривающие идею data locality. Данные "ближе" получить быстрее, чем данные "дальше". В L1 кеш процессора обратиться быстрее, чем в память, а в память быстрее, чем на жёсткий диск. Идея не ограничивается одной машиной, потому что запрос в тот же дата-центр также дешевле, чем в соседний.
Кеширование на уровне приложений — это как правило вынесение части данных в память. Но память не бесконечная, поэтому приходится придумывать алгоритмы инвалидации кеша, т.е. предполагать, какой элемент в кеше наименее полезен и выкидывать его. Про основные алгоритмы можно почитать здесь, но нам интересно погрызть гранит науки дальше.
Логично предположить, что элемент будет полезным, если его скоро вызовут ещё раз, т.е. на временной шкале два вызова находятся близко. Но инсайт заключается ещё и в том, что важность представляет не только расстояние во времени между вызовами, но также и частота этих вызовов. Техники, рассматривающие и оптимизирующие частотные и временные характеристики данных, относятся к идеи time locality по аналогии с data locality.
Нагрузки в реальных системах имеют непредсказуемый характер, а размер кеша ограничен. Какой элемент нужнее, который вызывался только что или который не вызывался давно, но за пару минут до этого был самым популярным по частоте вызовов? Пейпер показывает, приводит бенчмарки, и доказывает, что частота — тоже важный критерий для инвалидации кеша.
TinyLFU (Least frequently used) — это небольшая прослойка перед основным кешом, который может работать, например, на LRU. Её задача контролировать удаление данных в соответствие с частотой их вхождения. Основной кеш предлагает свой вариант, а TinyLFU решает, удалить ли то что предложил кеш или что-то другое. Подсчёт частоты может реализовываться через фильтр Блума с подсчётом или Count-min sketch (CM sketch).
Задача подсчёта частоты сама по себе не решается в лоб, поскольку смотреть просто на количество вхождений нельзя. Данные могут быть сначала очень полезны, но с течением времени их важность падает. Поэтому TinyLFU также использует технику ageing или cooling. Периодически или при достижении определенных условий, вес определенного ключа или набора ключей уменьшается. Таким образом, частота стремится к нулю, если не происходят повторные запросы.
Существует и другая особенность. Часто бывает удобнее все данные класть в кеш и получать только оттуда. Если все записи проходят через кеш, среди них скорее всего будут и одноразовые записи, которые лучше бы вообще не сохранять. Эта идея реализуется через механизм под названием doorkeeping. Смысл в том, чтобы при первом обращении класть данные в обычный LRU кеш, и только если по этим же ключам будут еще обращения, перекладывать их в основное хранилище в памяти. Размер doorkeeping области — параметр конфигурации кеша.
Все эти мысли и техники объединяются в пейпере в алгоритм W-TinyLFU (Window TinyLFU). Он используется в Java библиотеке Caffein. Это уже реализованная идея, опробованная в продакшене, протестированная, как на сгенерированных данных (Zipfian distribution, SPC1-like трейсы. Последнее — некий синтетический трейс для проверки I/O операций. Я нашёл упоминание только здесь), так и на реальных примерах. Алгоритм работает как минимум не хуже любого другого, а чаще немного лучше. Больше бенчмарков есть в самой работе.
Отдельно стоит отметить богатейшую теоретическую базу для этого исследования. Это аж 57 источников! Не каждая книга может похвастаться таким длинным списком. Если всё читать не хочется, основная выжимка, которая включает другие алгоритмы кеширования и инвалидации, представлена в доке Caffein в конце.
#shark_whitepaper
#shark_recommends
Работы как сегодняшняя (ссылка-клон) не позволяют делать по посту о пейперах раз в неделю, так как информации слишком много. Это исследование настолько открывает границы сознания, что его нужно перечитать несколько раз. Сначала, чтобы восхититься красотой идеи, затем чтобы понять суть.
Для начала отойдём на несколько шагов назад. Когда дело касается "оптимизации доступа", в первую очередь речь идет про техники, рассматривающие идею data locality. Данные "ближе" получить быстрее, чем данные "дальше". В L1 кеш процессора обратиться быстрее, чем в память, а в память быстрее, чем на жёсткий диск. Идея не ограничивается одной машиной, потому что запрос в тот же дата-центр также дешевле, чем в соседний.
Кеширование на уровне приложений — это как правило вынесение части данных в память. Но память не бесконечная, поэтому приходится придумывать алгоритмы инвалидации кеша, т.е. предполагать, какой элемент в кеше наименее полезен и выкидывать его. Про основные алгоритмы можно почитать здесь, но нам интересно погрызть гранит науки дальше.
Логично предположить, что элемент будет полезным, если его скоро вызовут ещё раз, т.е. на временной шкале два вызова находятся близко. Но инсайт заключается ещё и в том, что важность представляет не только расстояние во времени между вызовами, но также и частота этих вызовов. Техники, рассматривающие и оптимизирующие частотные и временные характеристики данных, относятся к идеи time locality по аналогии с data locality.
Нагрузки в реальных системах имеют непредсказуемый характер, а размер кеша ограничен. Какой элемент нужнее, который вызывался только что или который не вызывался давно, но за пару минут до этого был самым популярным по частоте вызовов? Пейпер показывает, приводит бенчмарки, и доказывает, что частота — тоже важный критерий для инвалидации кеша.
TinyLFU (Least frequently used) — это небольшая прослойка перед основным кешом, который может работать, например, на LRU. Её задача контролировать удаление данных в соответствие с частотой их вхождения. Основной кеш предлагает свой вариант, а TinyLFU решает, удалить ли то что предложил кеш или что-то другое. Подсчёт частоты может реализовываться через фильтр Блума с подсчётом или Count-min sketch (CM sketch).
Задача подсчёта частоты сама по себе не решается в лоб, поскольку смотреть просто на количество вхождений нельзя. Данные могут быть сначала очень полезны, но с течением времени их важность падает. Поэтому TinyLFU также использует технику ageing или cooling. Периодически или при достижении определенных условий, вес определенного ключа или набора ключей уменьшается. Таким образом, частота стремится к нулю, если не происходят повторные запросы.
Существует и другая особенность. Часто бывает удобнее все данные класть в кеш и получать только оттуда. Если все записи проходят через кеш, среди них скорее всего будут и одноразовые записи, которые лучше бы вообще не сохранять. Эта идея реализуется через механизм под названием doorkeeping. Смысл в том, чтобы при первом обращении класть данные в обычный LRU кеш, и только если по этим же ключам будут еще обращения, перекладывать их в основное хранилище в памяти. Размер doorkeeping области — параметр конфигурации кеша.
Все эти мысли и техники объединяются в пейпере в алгоритм W-TinyLFU (Window TinyLFU). Он используется в Java библиотеке Caffein. Это уже реализованная идея, опробованная в продакшене, протестированная, как на сгенерированных данных (Zipfian distribution, SPC1-like трейсы. Последнее — некий синтетический трейс для проверки I/O операций. Я нашёл упоминание только здесь), так и на реальных примерах. Алгоритм работает как минимум не хуже любого другого, а чаще немного лучше. Больше бенчмарков есть в самой работе.
Отдельно стоит отметить богатейшую теоретическую базу для этого исследования. Это аж 57 источников! Не каждая книга может похвастаться таким длинным списком. Если всё читать не хочется, основная выжимка, которая включает другие алгоритмы кеширования и инвалидации, представлена в доке Caffein в конце.
🔥1
Всё есть трейдофф
Трейдофф — решение, в рамках которого одни характеристики рассматриваемой системы улучшаются за счёт ухудшения других. Обычно трейдоффы рассматриваются в контексте технических решений. Например, добавим кеш — получим меньше latency, но больше потребление памяти. Добавим ещё 2 ноды в кластер из 3, получим больше availability, но усложним схождение консенсуса и возможно схватим проблем с консистентностью (CAP, вот это всё). В экономике есть схожее понятие — альтернативные издержки. Это максимальная потерянная выгода из-за принятого решения. Сколько бы можно было заработать, если вместо школы построить торговый центр? А если парковку вместо автомойки?
Трейдоффы — хороший способ ведения дискуссий. Можно спорить до хрипоты в поисках оптимального решения, а можно нарисовать табличку с плюсами и минусами каждого и отталкиваться от объективных фактов и метрик. Здесь правда сразу появятся две проблемы. Во-первых, не все факты объективны, а не все метрики можно быстро собрать. Во-вторых, факторов может быть очень много, так как практически всё есть часть трейдоффа. О некоторых таких факторах мы поговорим.
Рассмотрим ситуацию. Вы штурман в ралли-команде и готовитесь к новому маршруту. У вас много времени на подготовку, но маршрут для вас новый. Вы предполагаете с какой скоростью нужно проезжать разные участки маршрута и составляете на первый взгляд разумный план. Теперь вы мчите на трассе, одно колесо полуспущено, а вместо обещанного гравия на земле песок. По плану нужно лететь на X км/ч, но вы предпочитаете замедлиться, главное — доехать. Трасса не изменилась, но вы приняли разное решение при планировании и на дороге, потому что время на принятие решения и объём доступной информации — два важных фактора в трейдоффах. Можно потратить время и узнать больше о системе, а лишь затем принять решение, либо действовать прямо сейчас. К разработке эти два фактора относятся самым непосредственным образом. Никто не умеет правильно разделять системы на доменные области и вводить правильные абстракции с первого раза. Просто информации не хватит. Сделать сейчас как видно, а потом переделать — не просто разумный шаг, а единственно верный при отсутствии всей нужной информации и времени на её сбор.
Ещё один важный фактор — это сложность системы. Любое дополнение к продукту понижает его понятность, так как разбираться в отсутствующем коде не нужно. Сложность системы вступает в конфликт с несколькими другими факторами. Во-первых, с производительностью. Здесь я лучше Шипилёва не скажу (доклад + расшифровка), обязательный доклад вообще для всех. Во-вторых, сложность находится в конфликте со скоростью внесения дальнейших изменений. Чем труднее разобраться в текущем состоянии, тем сложнее это состояние поменять. Проблема здесь в том, что обе эти характеристики объективно подсчитать практически невозможно. Помогает только опыт и собранные грабли. Отдельно стоит сказать про "давайте всё перепишем с новым подходом". Период времени пока система будет находиться в состоянии между "старым" и "новым" варьируется и часто не заканчивается никогда. В безупречном мире система остаётся понятной и функционирующей даже в промежуточном состоянии, но этого бывает тяжело достичь.
Есть и много других интересных факторов. На каком языке писать? Это зависит и от размера коммьюнити, и от количества кандидатов на локальном рынка труда, и от бюджета, и лишь где-то в последнюю очередь от личных предпочтений, количества фичей и "модности" языка. Что выбрать, новую фичу в продукт или задачу из техдолга? Опять-таки, огромный вагон характеристик в трейдоффе. Финансовые показатели, на которые повлияет фича, время на реализацию, степень риска нестабильности продукта при откладывании техдолга, степень риска, что конкуренты реализуют фичу быстрее. Куда ни посмотри, любое решение — это трейдофф между десятками разных факторов. Только если учитывать все их можно сделать оптимальный выбор. А пока я в трейдоффе между карьерой и психологическим здоровьем выберу второе, и пойду смотреть сериальчики вместо литкода.
Трейдофф — решение, в рамках которого одни характеристики рассматриваемой системы улучшаются за счёт ухудшения других. Обычно трейдоффы рассматриваются в контексте технических решений. Например, добавим кеш — получим меньше latency, но больше потребление памяти. Добавим ещё 2 ноды в кластер из 3, получим больше availability, но усложним схождение консенсуса и возможно схватим проблем с консистентностью (CAP, вот это всё). В экономике есть схожее понятие — альтернативные издержки. Это максимальная потерянная выгода из-за принятого решения. Сколько бы можно было заработать, если вместо школы построить торговый центр? А если парковку вместо автомойки?
Трейдоффы — хороший способ ведения дискуссий. Можно спорить до хрипоты в поисках оптимального решения, а можно нарисовать табличку с плюсами и минусами каждого и отталкиваться от объективных фактов и метрик. Здесь правда сразу появятся две проблемы. Во-первых, не все факты объективны, а не все метрики можно быстро собрать. Во-вторых, факторов может быть очень много, так как практически всё есть часть трейдоффа. О некоторых таких факторах мы поговорим.
Рассмотрим ситуацию. Вы штурман в ралли-команде и готовитесь к новому маршруту. У вас много времени на подготовку, но маршрут для вас новый. Вы предполагаете с какой скоростью нужно проезжать разные участки маршрута и составляете на первый взгляд разумный план. Теперь вы мчите на трассе, одно колесо полуспущено, а вместо обещанного гравия на земле песок. По плану нужно лететь на X км/ч, но вы предпочитаете замедлиться, главное — доехать. Трасса не изменилась, но вы приняли разное решение при планировании и на дороге, потому что время на принятие решения и объём доступной информации — два важных фактора в трейдоффах. Можно потратить время и узнать больше о системе, а лишь затем принять решение, либо действовать прямо сейчас. К разработке эти два фактора относятся самым непосредственным образом. Никто не умеет правильно разделять системы на доменные области и вводить правильные абстракции с первого раза. Просто информации не хватит. Сделать сейчас как видно, а потом переделать — не просто разумный шаг, а единственно верный при отсутствии всей нужной информации и времени на её сбор.
Ещё один важный фактор — это сложность системы. Любое дополнение к продукту понижает его понятность, так как разбираться в отсутствующем коде не нужно. Сложность системы вступает в конфликт с несколькими другими факторами. Во-первых, с производительностью. Здесь я лучше Шипилёва не скажу (доклад + расшифровка), обязательный доклад вообще для всех. Во-вторых, сложность находится в конфликте со скоростью внесения дальнейших изменений. Чем труднее разобраться в текущем состоянии, тем сложнее это состояние поменять. Проблема здесь в том, что обе эти характеристики объективно подсчитать практически невозможно. Помогает только опыт и собранные грабли. Отдельно стоит сказать про "давайте всё перепишем с новым подходом". Период времени пока система будет находиться в состоянии между "старым" и "новым" варьируется и часто не заканчивается никогда. В безупречном мире система остаётся понятной и функционирующей даже в промежуточном состоянии, но этого бывает тяжело достичь.
Есть и много других интересных факторов. На каком языке писать? Это зависит и от размера коммьюнити, и от количества кандидатов на локальном рынка труда, и от бюджета, и лишь где-то в последнюю очередь от личных предпочтений, количества фичей и "модности" языка. Что выбрать, новую фичу в продукт или задачу из техдолга? Опять-таки, огромный вагон характеристик в трейдоффе. Финансовые показатели, на которые повлияет фича, время на реализацию, степень риска нестабильности продукта при откладывании техдолга, степень риска, что конкуренты реализуют фичу быстрее. Куда ни посмотри, любое решение — это трейдофф между десятками разных факторов. Только если учитывать все их можно сделать оптимальный выбор. А пока я в трейдоффе между карьерой и психологическим здоровьем выберу второе, и пойду смотреть сериальчики вместо литкода.
🔥1
Вас уже сотня человек! Спасибо всем большое, что читаете, я все ещё радуюсь каждому новому подписчику 🎉
В честь знаменательной даты, распишу план на ближайшие месяцы (годы):
- Запилить сайт. Иногда хочется делать разборы пейперов с картинками, возможно даже с анимашками. При этом закрываться за пейволом медиума ну такое. Это план на долго вперёд, мб к концу года и появится.
- Больше циклов про распределенные системы: как минимум разбор пейперов по алгоритмам failure detection, leader election, а также моделям консистентности и алгоритмам консенсуса. Хочется сделать полезный ресурс в стиле Jepsen, но с дорожной картой по топикам распределённых систем.
- Классические пейперы по базам данных: про ARIES, про B-Trees и прочее.
- Рандомные посты про всё на свете: От мотивации до архитектуры.
- Возможно несколько работ по обучению как науке, т.к. недавно заинтересовался темой.
А и конечно же важный опрос!
В честь знаменательной даты, распишу план на ближайшие месяцы (годы):
- Запилить сайт. Иногда хочется делать разборы пейперов с картинками, возможно даже с анимашками. При этом закрываться за пейволом медиума ну такое. Это план на долго вперёд, мб к концу года и появится.
- Больше циклов про распределенные системы: как минимум разбор пейперов по алгоритмам failure detection, leader election, а также моделям консистентности и алгоритмам консенсуса. Хочется сделать полезный ресурс в стиле Jepsen, но с дорожной картой по топикам распределённых систем.
- Классические пейперы по базам данных: про ARIES, про B-Trees и прочее.
- Рандомные посты про всё на свете: От мотивации до архитектуры.
- Возможно несколько работ по обучению как науке, т.к. недавно заинтересовался темой.
А и конечно же важный опрос!
🔥1
Отзыв на Database Internals
#shark_recommends
Пару месяцев назад тот-самый Martin Kleppmann, автор книжки с кабанчиком, был автором недели в слаке DataTalks (ссылка на слак там же). Это такое интересное мероприятие, когда автор какой-нибудь книжки в основном по data science или ml в течение недели отвечает на любые вопросы участников. На следующей после него неделе рассматривалась книжка Database Internals от Alex Petrov, которая для меня стала настоящим открытием!
Книга поделена на две части. Первая полностью про архитектуру БД, преимущественно о хранении. И это самая подробная таксономизация алгоритмов хранения в базах данных, которая мне пока что встречалась в литературе. Не, я конечно слышал, что там в постгре используется B-tree, но этих самых B-tree оказывается сильно больше, чем 5 видов, так ещё для каждого мешок разных оптимизаций. Забавно как можно каждый день пользоваться БД, при этом иметь очень посредственное представление, как оно там работает... Однозначно рекомендую.
Вторая часть про распределенные системы. Здесь снова больше про алгоритмы, чем про "построение правильных приложений". Вот вам 4 вида Gossip и 6 разных Paxos'ов, разбирайтесь! Благо есть ссылки на все 222 пейпера-источника. Половину из них мы здесь ещё рассмотрим. 💪
Если вы думали, что почитать про распределенные системы после книжки с кабанчиком или просто всегда хотели узнать, как там база данных внутри двигает битики, однозначно читайте, не пожалеете.
#shark_recommends
Пару месяцев назад тот-самый Martin Kleppmann, автор книжки с кабанчиком, был автором недели в слаке DataTalks (ссылка на слак там же). Это такое интересное мероприятие, когда автор какой-нибудь книжки в основном по data science или ml в течение недели отвечает на любые вопросы участников. На следующей после него неделе рассматривалась книжка Database Internals от Alex Petrov, которая для меня стала настоящим открытием!
Книга поделена на две части. Первая полностью про архитектуру БД, преимущественно о хранении. И это самая подробная таксономизация алгоритмов хранения в базах данных, которая мне пока что встречалась в литературе. Не, я конечно слышал, что там в постгре используется B-tree, но этих самых B-tree оказывается сильно больше, чем 5 видов, так ещё для каждого мешок разных оптимизаций. Забавно как можно каждый день пользоваться БД, при этом иметь очень посредственное представление, как оно там работает... Однозначно рекомендую.
Вторая часть про распределенные системы. Здесь снова больше про алгоритмы, чем про "построение правильных приложений". Вот вам 4 вида Gossip и 6 разных Paxos'ов, разбирайтесь! Благо есть ссылки на все 222 пейпера-источника. Половину из них мы здесь ещё рассмотрим. 💪
Если вы думали, что почитать про распределенные системы после книжки с кабанчиком или просто всегда хотели узнать, как там база данных внутри двигает битики, однозначно читайте, не пожалеете.
🔥1
Epidemic Algorithms for Replicated Database Maintenance (1/2)
#shark_whitepaper
Классическая дремучая работа из 1987 года, когда самыми крутыми компаниями в IT были Xerox и IBM, которая в будущем станет основой для большинства алгоритмов поиска сбоев (failure detection) и уменьшения энтропии (entropy reduction). Благодаря этой работе появится, например целая семья алгоритмов-протоколов с общий названием gossip. Они используются практически везде, где есть необходимость поддерживать несколько узлов, например в Consul, Cassandra, AWS S3 (раскрывают в постмортеме) и в десятках других продакшон-грейд продуктах.
Эпидемические алгоритмы/протоколы так называются не случайно, а в честь особого вида математики, изучающего распространение эпидемий. Да, такая математика тоже существует. Вот например целая книжка по теме, очень актуально. Только в случае с алгоритмами цель — заразить наибольшее количество узлов, а не предотвратить заражение. Эдакий Plague Inc на транзисторах.
Терминология берётся из всё той же математики эпидемий. Узлы сети разделяются на 3 вида:
- susceptible — ещё не получили обновление.
- infective — уже получили и распространяют.
- removed — уже получили и не распространяют.
Задача стоит в том, чтобы распространить обновление по распределенной сети узлов, при этом уменьшить число узлов, которые ни разу не получили обновление, т.е. остались susceptible (такие узлы называются residue). При этом эпидемия должна завершиться за минимальное количество сообщений (traffic), а также алгоритм должен сойтись (convergence) максимально быстро. Сходимость измеряется как по среднему времени, так и по времени между первым и последним сообщением.
Эпидемия начинается с того, что некий узел переходит в состояние infective, и начинает распространять обновления. Их распространение происходит на случайным образом выбранные соседние узлы. После попытки заражения, узел с заранее заданной вероятностью
- Blind / Feedback. При blind распространении узел всегда после отправки сообщения проверяет, нужно ли ему перейти в removed. При feedback только если новая нода уже получала обновление. Использование feedback увеличивает трафик, так как нужно вернуть и ответ, но зато позволяет резко сократить процент residue узлов после завершения пандемии.
- Counter / Coin. В общем случае, узел переходит в removed с вероятностью
- Push / Pull. Обычно узлы заражают соседей по push модели, так как рассылают сообщения сами. Можно сделать алгоритм наоборот, когда все узлы сети сами начнут запрашивать сообщения от соседей. При наличии большого количества эпидемий одновременно, это работает даже лучше, чем push (пруфы в статье, спойлер: там матан с производными), но генерирует больше трафика. Оба подхода можно использовать одновременно в push-pull модели.
#shark_whitepaper
Классическая дремучая работа из 1987 года, когда самыми крутыми компаниями в IT были Xerox и IBM, которая в будущем станет основой для большинства алгоритмов поиска сбоев (failure detection) и уменьшения энтропии (entropy reduction). Благодаря этой работе появится, например целая семья алгоритмов-протоколов с общий названием gossip. Они используются практически везде, где есть необходимость поддерживать несколько узлов, например в Consul, Cassandra, AWS S3 (раскрывают в постмортеме) и в десятках других продакшон-грейд продуктах.
Эпидемические алгоритмы/протоколы так называются не случайно, а в честь особого вида математики, изучающего распространение эпидемий. Да, такая математика тоже существует. Вот например целая книжка по теме, очень актуально. Только в случае с алгоритмами цель — заразить наибольшее количество узлов, а не предотвратить заражение. Эдакий Plague Inc на транзисторах.
Терминология берётся из всё той же математики эпидемий. Узлы сети разделяются на 3 вида:
- susceptible — ещё не получили обновление.
- infective — уже получили и распространяют.
- removed — уже получили и не распространяют.
Задача стоит в том, чтобы распространить обновление по распределенной сети узлов, при этом уменьшить число узлов, которые ни разу не получили обновление, т.е. остались susceptible (такие узлы называются residue). При этом эпидемия должна завершиться за минимальное количество сообщений (traffic), а также алгоритм должен сойтись (convergence) максимально быстро. Сходимость измеряется как по среднему времени, так и по времени между первым и последним сообщением.
Эпидемия начинается с того, что некий узел переходит в состояние infective, и начинает распространять обновления. Их распространение происходит на случайным образом выбранные соседние узлы. После попытки заражения, узел с заранее заданной вероятностью
k переходит в состояние removed, т.е. перестает распространять обновления. Эпидемия завершается, когда в сети отсутствуют infective узлы, т.е. все узлы либо уже распространили и перешли в removed, либо никогда не получили обновление и остались в susceptible. Процесс заражения можно разделить по нескольким критериями:- Blind / Feedback. При blind распространении узел всегда после отправки сообщения проверяет, нужно ли ему перейти в removed. При feedback только если новая нода уже получала обновление. Использование feedback увеличивает трафик, так как нужно вернуть и ответ, но зато позволяет резко сократить процент residue узлов после завершения пандемии.
- Counter / Coin. В общем случае, узел переходит в removed с вероятностью
1/k, т.е. по броску k-гранной монетки. Подход counter значит, что узел не бросает монетку, а отключается только после n отправленных сообщений. Трейдофф здесь между "хранить счётчик" и не хранить. Кажется мелочь, но в системе может одновременно происходить несколько волн эпидемии с разными обновлениями, а счётчик нужно хранить на каждую из них на всех infective узлах, так что накладные расходы могут быть большими. Возможно также использовать и комбинированный подход, когда сначала отсылается n сообщений, а затем узел отключается с вероятностью k.- Push / Pull. Обычно узлы заражают соседей по push модели, так как рассылают сообщения сами. Можно сделать алгоритм наоборот, когда все узлы сети сами начнут запрашивать сообщения от соседей. При наличии большого количества эпидемий одновременно, это работает даже лучше, чем push (пруфы в статье, спойлер: там матан с производными), но генерирует больше трафика. Оба подхода можно использовать одновременно в push-pull модели.
🔥1
Epidemic Algorithms for Replicated Database Maintenance (2/2)
Замечательные рассуждения приводятся и об удаление данных при эпидемиях. Недостаточно отправить сообщение "удалить данные", потому что при наличии конкурирующих сообщений с изменениями, эпидемия по обновлению может перебороть эпидемию по удалению. Поэтому приходится хранить death certificate — некоторое сообщение, при получении которого все более старые сообщения можно игнорировать. Эти сообщения нужно хранить какое-то время, но не всё так просто.
Во-первых, выбрать правильное время хранения тяжело, т.к. в большой сети может всегда существовать недоступный узел, при этом недоступным он может быть долго, например дольше времени хранения. Во-вторых, всегда есть вероятность наличия residual узлов, которые вообще не получили информацию об удалении. При этом, существующие сертификаты тоже нужно когда-то удалять, так как они бесполезны, а место занимают.
В таких случаях можно использовать как минимум две техники. Первая — это использовать вместе с эпидемическим алгоритмом дополнительный способ синхронизации. Вторая — хранить death certificate на некоторых нодах в спящем состоянии. Когда такой узел получает обновление для спящего мертвого сертификата, он пробуждает сертификат и запускает новую эпидемию по удалению этого уже, казалось бы, удаленного элементы. Тут мы успешно перейдем к производной первой проблемы — когда удалить спящий сертификат...
Есть и другая сложность. Часть обновлений — это в самом деле легальное "возрождение" ранее убитых данных. Решить её в статье предлагается через заведение второго таймштампа. Один используется при обычных обновлениях, второй для активизации после удаления. Если узел активизирован после таймштампа сертификата, значит сертификат неверен и все узлы, которые одновременно пытаются распространить и удаление и обновление, должны прекратить распространять удаление и вообще уничтожить свой death certificate.
В заключении работы рассматривается, как вообще такие алгоритмы работает в реальных сетях, где узлы находятся на разном расстоянии, но при этом все соединены. Вывод в целом очевиден: эффективнее построить пространственный индекс (spatial index) и ходить по более близким элементам с большей вероятностью, чем по менее близким. При чем пруф есть как математический (который я не понял ¯\_(ツ)_/¯), так и экспериментальный. А вот если взять более необычные топологии сети, например когда узлы соединены в мини-кластеры и лишь малая часть нод общается между кластерами, тут всё становится ужасно как во времени сходимости так и в проценте residual узлов. И если pull-модель ещё как-то справляется, то push-модель при симуляциях может вообще не выйти за пределы одного кластера.
Замечательные рассуждения приводятся и об удаление данных при эпидемиях. Недостаточно отправить сообщение "удалить данные", потому что при наличии конкурирующих сообщений с изменениями, эпидемия по обновлению может перебороть эпидемию по удалению. Поэтому приходится хранить death certificate — некоторое сообщение, при получении которого все более старые сообщения можно игнорировать. Эти сообщения нужно хранить какое-то время, но не всё так просто.
Во-первых, выбрать правильное время хранения тяжело, т.к. в большой сети может всегда существовать недоступный узел, при этом недоступным он может быть долго, например дольше времени хранения. Во-вторых, всегда есть вероятность наличия residual узлов, которые вообще не получили информацию об удалении. При этом, существующие сертификаты тоже нужно когда-то удалять, так как они бесполезны, а место занимают.
В таких случаях можно использовать как минимум две техники. Первая — это использовать вместе с эпидемическим алгоритмом дополнительный способ синхронизации. Вторая — хранить death certificate на некоторых нодах в спящем состоянии. Когда такой узел получает обновление для спящего мертвого сертификата, он пробуждает сертификат и запускает новую эпидемию по удалению этого уже, казалось бы, удаленного элементы. Тут мы успешно перейдем к производной первой проблемы — когда удалить спящий сертификат...
Есть и другая сложность. Часть обновлений — это в самом деле легальное "возрождение" ранее убитых данных. Решить её в статье предлагается через заведение второго таймштампа. Один используется при обычных обновлениях, второй для активизации после удаления. Если узел активизирован после таймштампа сертификата, значит сертификат неверен и все узлы, которые одновременно пытаются распространить и удаление и обновление, должны прекратить распространять удаление и вообще уничтожить свой death certificate.
В заключении работы рассматривается, как вообще такие алгоритмы работает в реальных сетях, где узлы находятся на разном расстоянии, но при этом все соединены. Вывод в целом очевиден: эффективнее построить пространственный индекс (spatial index) и ходить по более близким элементам с большей вероятностью, чем по менее близким. При чем пруф есть как математический (который я не понял ¯\_(ツ)_/¯), так и экспериментальный. А вот если взять более необычные топологии сети, например когда узлы соединены в мини-кластеры и лишь малая часть нод общается между кластерами, тут всё становится ужасно как во времени сходимости так и в проценте residual узлов. И если pull-модель ещё как-то справляется, то push-модель при симуляциях может вообще не выйти за пределы одного кластера.
🔥1
Consistent Hashing и Akamai Technologies (1/2)
#shark_whitepaper
Я честно пытался написать привычный tl/dr по работе по консистентному хешированию (Consistent Hashing and Random Trees: Distributed Caching Protocols for Relieving Hot Spots on the World Wide Web), но пока готовился, понял, что интереснее даже не сама работа, а то, как развивался мир после нее. Кому все-таки хочется хардкора, матан начинается с четвёртой страницы и не заканчивается до самого конца. А если вы в первый раз видите словосочетание «консистентное хеширование» то советую посмотреть ссылка один просто хорошая и ссылка два лекция Стенфорда. Матана там нет, я проверил.
Сначала о работе. Идея заключается в том, чтобы выстраивать кеши друг за другом в Random Tree. Каждой странице при помощи случайной равномерной хеш-функции
Поскольку сеть в целом нестабильная, а нагрузка даже без swamping узлов может расти, нужно как-то добавлять дополнительные ноды в сеть и поднимать старые. Но ведь мы использует хеш-функции для определения пути от первого кеша до сервера. Обычно при изменении размера хеш-таблицы (в нашем случае, при вылете ноды), нужно заново вычислять значение хеш-функции для большинства ключей. Здесь как раз на помощь и приходит consistent hashing. Если использовать консистентную хеш-функцию в качестве функции
#shark_whitepaper
Я честно пытался написать привычный tl/dr по работе по консистентному хешированию (Consistent Hashing and Random Trees: Distributed Caching Protocols for Relieving Hot Spots on the World Wide Web), но пока готовился, понял, что интереснее даже не сама работа, а то, как развивался мир после нее. Кому все-таки хочется хардкора, матан начинается с четвёртой страницы и не заканчивается до самого конца. А если вы в первый раз видите словосочетание «консистентное хеширование» то советую посмотреть ссылка один просто хорошая и ссылка два лекция Стенфорда. Матана там нет, я проверил.
Сначала о работе. Идея заключается в том, чтобы выстраивать кеши друг за другом в Random Tree. Каждой странице при помощи случайной равномерной хеш-функции
h присваивается некий путь от первого кеша до вершины. Таких функцию несколько, т.е. есть больше чем 1 путь, по которому можно получить страницу. Браузер может вычислить этот путь, выбрав одну из хеш-фунцию. Запрос приходит на первый кеш, и если тот содержит страницу, отдаёт её, а если нет, направляет запрос на следующий кеш. Тот на следующий, на следующий и так до тех пор, пока запрос не доберётся до сервера, где страница уж точно есть. Страница сохраняется в кеше только после того, как кеш увидит запрос этой страницы несколько раз. Здесь важно, что у каждой страницы несколько случайных путей по дереву кешей в зависимости от выбранной хеш-функции. Разные клиенты будут получать разный путь к одной и той же странице, эффективно размазывая её по всему дереву кешей, что позволяет избавиться от перегруженных нод. В работе перегруженные ноды называют swamping. Доказательство того, что такое размазывание работает тоже есть. Поскольку сеть в целом нестабильная, а нагрузка даже без swamping узлов может расти, нужно как-то добавлять дополнительные ноды в сеть и поднимать старые. Но ведь мы использует хеш-функции для определения пути от первого кеша до сервера. Обычно при изменении размера хеш-таблицы (в нашем случае, при вылете ноды), нужно заново вычислять значение хеш-функции для большинства ключей. Здесь как раз на помощь и приходит consistent hashing. Если использовать консистентную хеш-функцию в качестве функции
h ещё на самом первом шаге при выборе случайного пути, можно добиться того, что большая часть случайных путей не будет перестраиваться при добавлении или удалении новых нод из сети.🔥1
Consistent Hashing и Akamai Technologies (2/2)
А теперь история. Двое из авторов работы Daniel Lewin и Frank Leighton — основатели Akamai Technologies. Компания делает CDN и security решения. Это Cloudflare/Fastly в мире ентерпрайза. Через них проходит по разным оценкам до 30% всего трафика в мире. Работа датируется 1997 годом и говорит как раз о том, как эффективно раздавать страницы в Интернете. В 1998 году авторы попали в финал конкурса MIT $50к Entrepreneurship Competition (сейчас MIT $100k. Инфляция!), основав в этом же году компанию. Собственно на двух идеях из работы: Random Trees и Consistent hashing, и основана архитектура Akamai CDN.
31 марта 1999 года происходит знаменательное событие для Akamai и для мира. В свет выходят Звездные войны. Эпизод 1: Скрытая угроза. Да ещё и онлайн. «Онлайн» в конце 20 века до появления ютуба значило «Вы можете скачать файл в формате Real Video, QuickTime или AVI и посмотреть на своем ПК». Официальный и эксклюзивный дистрибьютор — apple.com. Собственно, apple.com практически сразу же падает и продолжает лежать недоступным на протяжении половины дня. Но сеть Akamai, которая уже успешно справилась с раздачей более миллиона копий трейлера звездных войн за сутки, продолжает жить. PR скандала не случилось.
01 апреля 1999 года Стив Джобс решает лично позвонить одному из сооснователей компании Paul Segan, но тот принимает звоном за первоапрельскую шутку своих коллег и кладет трубку. На сотрудничество компаний этот инцидент не повлиял.
11 сентября 2001 года трагически погибает один из основателей Akamai и соавторов работы Daniel Lewin. Убит одним из террористов на борту самолёта American Airlines Flight 11, который врезался в первую, северную башню Всемирного торгового центра.
2001 год: консистентное хеширование начинает применяться в первых P2P сетях. В таких сетях нужно чтобы все узлы могли знать, где лежит какой файл. Первые версии, например Napster, хранили такую информацию централизовано, что позволяет легко отключить всю сеть при падении главного узла. Далее ко второму поколению, например сеть Gnutella, появилась идея раздавать такую информацию через broadcast. Это работало пока узлов в сети было мало. Наконец третье поколение P2P сетей, начиная с Chord, уже начали использовать консистентное хеширование. Преимуществом такого хеширования для P2P является то, что не обязательно знать о расположении всех остальных серверов в сети. Достаточно знать несколько, которые находятся рядом. Частично даже современный BitTorrent продолжает использовать consistent hashing.
2006 год: Амазон запускает пока недоступную для широкой общественности Dynamo, которая тоже использует консистентное хеширование для партиционирования и репликации. Цель — хранить максимум информации надежно на простом железе и быстро её раздавать. Это важная веха, так как Амазон через год также публикует вот эту работу (Dynamo: Amazon’s Highly Available Key-value Store).
В дальнейшем consistent hashing стал применяться и в Cassandra, и в Ryak, и в Couchbase, Akka, Gluster, и ещё в десятках других продуктах. Сейчас это одна из базовых структур данных / алгоритмов для построения сетей с частой сменой количества участников.
А теперь история. Двое из авторов работы Daniel Lewin и Frank Leighton — основатели Akamai Technologies. Компания делает CDN и security решения. Это Cloudflare/Fastly в мире ентерпрайза. Через них проходит по разным оценкам до 30% всего трафика в мире. Работа датируется 1997 годом и говорит как раз о том, как эффективно раздавать страницы в Интернете. В 1998 году авторы попали в финал конкурса MIT $50к Entrepreneurship Competition (сейчас MIT $100k. Инфляция!), основав в этом же году компанию. Собственно на двух идеях из работы: Random Trees и Consistent hashing, и основана архитектура Akamai CDN.
31 марта 1999 года происходит знаменательное событие для Akamai и для мира. В свет выходят Звездные войны. Эпизод 1: Скрытая угроза. Да ещё и онлайн. «Онлайн» в конце 20 века до появления ютуба значило «Вы можете скачать файл в формате Real Video, QuickTime или AVI и посмотреть на своем ПК». Официальный и эксклюзивный дистрибьютор — apple.com. Собственно, apple.com практически сразу же падает и продолжает лежать недоступным на протяжении половины дня. Но сеть Akamai, которая уже успешно справилась с раздачей более миллиона копий трейлера звездных войн за сутки, продолжает жить. PR скандала не случилось.
01 апреля 1999 года Стив Джобс решает лично позвонить одному из сооснователей компании Paul Segan, но тот принимает звоном за первоапрельскую шутку своих коллег и кладет трубку. На сотрудничество компаний этот инцидент не повлиял.
11 сентября 2001 года трагически погибает один из основателей Akamai и соавторов работы Daniel Lewin. Убит одним из террористов на борту самолёта American Airlines Flight 11, который врезался в первую, северную башню Всемирного торгового центра.
2001 год: консистентное хеширование начинает применяться в первых P2P сетях. В таких сетях нужно чтобы все узлы могли знать, где лежит какой файл. Первые версии, например Napster, хранили такую информацию централизовано, что позволяет легко отключить всю сеть при падении главного узла. Далее ко второму поколению, например сеть Gnutella, появилась идея раздавать такую информацию через broadcast. Это работало пока узлов в сети было мало. Наконец третье поколение P2P сетей, начиная с Chord, уже начали использовать консистентное хеширование. Преимуществом такого хеширования для P2P является то, что не обязательно знать о расположении всех остальных серверов в сети. Достаточно знать несколько, которые находятся рядом. Частично даже современный BitTorrent продолжает использовать consistent hashing.
2006 год: Амазон запускает пока недоступную для широкой общественности Dynamo, которая тоже использует консистентное хеширование для партиционирования и репликации. Цель — хранить максимум информации надежно на простом железе и быстро её раздавать. Это важная веха, так как Амазон через год также публикует вот эту работу (Dynamo: Amazon’s Highly Available Key-value Store).
В дальнейшем consistent hashing стал применяться и в Cassandra, и в Ryak, и в Couchbase, Akka, Gluster, и ещё в десятках других продуктах. Сейчас это одна из базовых структур данных / алгоритмов для построения сетей с частой сменой количества участников.
🔥1