Распределенные системы: распространенные ошибки и сложности

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

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

Распределенные системы и сложность

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

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

Сложность

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

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

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

Монолитная архитектура

Монолитная архитектура — отличный пример централизованной системы. Она представлена в виде одного развёртываемого и исполняемого компонента. Например, такие компоненты могут содержать пользовательский интерфейс и различные модули, расположенные в одном месте.

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

- Невозможность независимого масштабирования модулей

- Сложнее контролировать растущую сложность

- Отсутствие возможности независимого развертывания модулей

- Сложно поддерживать огромную базу данных кодов

- Взаимодействие технологий и поставщиков

Архитектура микросервисов

Микросервисная архитектура — это архитектурный стиль и разновидность сервисно-ориентированной архитектуры, которая структурирует систему как набор слабосвязанных сервисов. Например, компании, счета, клиенты и пользовательский интерфейс представлены как отдельные процессы, развёрнутые на нескольких узлах.

У всех этих сервисов есть своя собственная база данных, которую можно использовать время от времени, но это, вероятно, плохая практика или антипаттерн.

Такая архитектура имеет ряд преимуществ.

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

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

- Географическое распределение : если у всех нас есть клиенты в США, Европе или Азии и мы также хотим предоставить нашим клиентам наилучший опыт, нам необходимо распространить эти услуги по всему миру и организовать более сложные методы репликации данных.

- Выбор технологий : вы свободны в выборе решений.

Атрибуты качества

Существует три основных атрибута качества, которыми на том или ином уровне обладает любая система:

- Надёжность : способность продолжать корректно функционировать, несмотря на трудности, то есть быть отказоустойчивой или отказоустойчивой. Даже если система работает надёжно сейчас, это не гарантирует надёжности в будущем. Частой причиной снижения производительности является увеличение нагрузки: например, количество одновременно работающих пользователей системы может увеличиться с 10 000 до 100 000 или с 1 миллиона до 10 миллионов.

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

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

Каковы основные проблемы?

Ненадежные сети

Существует множество причин, по которым сети ненадежны, например:

- Ваш запрос мог быть утерян.

- Ваш запрос может ожидать в очереди и будет доставлен позже.

- Удаленный узел мог выйти из строя (возможно, он вышел из строя или был отключен).

- Удаленный узел мог временно перестать отвечать.

- Удаленный узел, возможно, обработал ваш запрос, но ответ был потерян в сети.

- Удаленный узел, возможно, обработал ваш запрос, но ответ был задержан и будет доставлен позже.

Стратегия: Timeout

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

Стратегия: Повторить попытку

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

Стратегия: идемпотентность

Чтобы избежать этого, мы можем использовать технику, называемую идемпотентностью.

Концепция идемпотентности подразумевает, что многократное выполнение одного и того же действия даёт тот же эффект, что и однократное. Для реализации свойства «точно один раз» можно использовать решение, прикрепляющее к запросу ключ идемпотентности. При повторной попытке выполнить тот же запрос с идентичным ключом идемпотентности сервер проверит, что запрос с таким ключом уже был обработан, и просто вернёт предыдущий ответ. Следовательно, любое количество повторных попыток с тем же ключом не окажет негативного влияния на поведение системы.

Стратегия: автоматический выключатель

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

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

Параллелизм и потерянные записи

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

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

Стратегия: изоляция моментальных снимков

Аббревиатура ACID расшифровывается как «атомарность», «консистентность», «изоляция» и «долговечность». Все популярные базы данных SQL поддерживают эти свойства.

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

Это позволяет гарантировать, что другой поток не увидит полузавершённый результат операции.

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

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

- Долговечность гарантирует, что после завершения транзакции все данные будут сохранены в безопасности.

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

Стратегия: сравнить и установить

Большинство баз данных NoSQL не поддерживают свойства ACID, выбирая BASE, при котором такие базы данных сравнивают данные и используют набор. Цель этой операции — избежать потери обновлений, позволяя выполнять обновление только в том случае, если значение не изменилось с момента последнего чтения. Если текущее значение не соответствует ранее прочитанному, обновление не имеет эффекта, и цикл «чтение-изменение-запись» необходимо повторить.

Например, Cassandra обеспечивает легкие транзакции, которые позволяют вам использовать различные IF, IF NOT EXISTS, и IF EXISTSусловные операторы для предотвращения проблем с параллелизмом.

Стратегия: Аренда

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

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

Проблема двойной записи

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

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

Стратегия: транзакционные исходящие сообщения

Одним из возможных решений является реализация транзакционного исходящего ящика . Это предполагает хранение событий в таблице «OutboxEvents» в рамках той же транзакции, что и сама операция. Благодаря атомарности процесса, в случае сбоя транзакции данные не будут сохранены.

Другим необходимым компонентом является Relay, который регулярно опрашивает таблицу OutboxEvents и отправляет сообщения получателям. Такой подход позволяет гарантировать как минимум одну доставку. Тем не менее, это не является проблемой, поскольку все получатели должны быть идемпотентными из-за ненадёжности сети.

Стратегия: Отслеживание журналов

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

У этого подхода есть свои преимущества и недостатки. Например, он требует интеграции с решениями баз данных, но позволяет писать меньше кода в приложении.

Ненадежные часы

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

В компьютерах используются два основных типа часов: часы с точным временем суток и монотонные часы. Часы с точным временем суток показывают дату и время в соответствии с определённым календарём и обычно синхронизируются с помощью сетевого протокола времени (NTP). Однако задержки и сетевые проблемы могут повлиять на процесс синхронизации, приводя к рассинхронизации часов. Монотонные часы непрерывно идут вперёд, что делает их подходящими для измерения длительностей.

Однако монотонно возрастающее значение уникально для каждого компьютера, что ограничивает их использование для сравнения даты и времени на нескольких серверах. Достижение высокой точности синхронизации часов — непростая задача. В большинстве случаев необходимость в таком решении неочевидна. Однако в случаях, когда соблюдение нормативных требований требует его использования, можно использовать протокол точного времени (Precision Time Protocol), хотя это потребует значительных инвестиций.

Доступность и последовательность

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

Рассмотрим сценарий, в котором два клиента читают данные с разных узлов: один с основного узла, а другой с ведомого. Репликация настроена на обновление ведомых узлов после смены ведущего узла. Однако что произойдёт, если по какой-то причине ведущее устройство перестанет отвечать?

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

Тип консистенции

Для описания гарантий используются два основных класса согласованности.

- Слабая согласованность (или в конечном итоге слабая согласованность) означает, что данные будут синхронизированы на всех последователях через некоторое время, если вы прекратите вносить изменения в лидера.

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

Стратегия: алгоритм распределенного консенсуса (например, Raft)

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

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

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

Стратегия: прочтите мнение лидера

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

Вместо заключения

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

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

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

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

Распределенные системы: распространенные ошибки и сложности
Получить консультацию у специалистов DST
Напишите нам прямо сейчас, наши специалисты расскажут об услугах и ответят на все ваши вопросы.
Комментарии и отзывы экспертов
RSS
09:35
+3
Действительно, распределенные системы — это настоящий вызов для разработчиков. Особенно сложно бывает справиться с проблемой консистентности данных, когда разные узлы системы могут находиться в несогласованном состоянии. На практике часто сталкиваюсь с тем, что команды недооценивают важность правильного выбора алгоритма консенсуса, что впоследствии приводит к серьезным проблемам с производительностью и надежностью. Хотелось бы добавить, что одной из частых ошибок является недостаточное внимание к мониторингу и логированию. Без качественного сбора метрик и анализа логов очень сложно оперативно выявлять и устранять возникающие проблемы. Также важно помнить о необходимости тщательного тестирования отказоустойчивости на ранних этапах разработки, а не когда система уже работает в продакшене.
09:36
+2
Полностью согласен с автором относительно проблем синхронизации в распределенных системах. Хочу поделиться своим опытом: в одном из проектов мы столкнулись с классической проблемой гонщиков (race condition) при обновлении данных несколькими узлами одновременно. Решение пришло через внедрение оптимистичного подхода с версионированием объектов, что существенно снизило количество конфликтов. Отдельно хочу отметить важность правильного подхода к шардированию данных. Многие команды пытаются сразу создать идеальную схему распределения, не понимая, что потребности системы могут существенно измениться со временем. Гибкость в этом вопросе критически важна. Также стоит уделить внимание сетевой задержке между узлами — это часто упускаемый фактор, который может серьезно повлиять на производительность всей системы.
09:37
+1
Вопрос распределенных систем и связанных с ними ошибок очень актуален в наше время, особенно с учетом того, что технологии продолжают развиваться с неимоверной скоростью. Основная сложность заключается в том, что компоненты распределенной системы могут находиться в разных географических точках, что порождает разнообразные проблемы, такие как задержка связи и потеря пакетов.

Эти факторы способны негативно отразиться на производительности всей системы и вызвать сбои в работе приложений. Более того, ошибки, возникающие в одном компоненте, могут иметь цепной реакцией, влияя на другие части системы, что создает дополнительные трудности в их отладке и поддержке.
09:37
Распределенные системы предоставляют широкие возможности для повышения надежности и масштабируемости приложений, однако с их внедрением возникают и определенные риски. Поскольку такие системы состоят из множества взаимосвязанных элементов, проанализировать потенциальные точки отказа становится задачей не из легких.

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

К тому же, в распределенной архитектуре важно тщательно контролировать состояние всех компонентов в реальном времени, чтобы минимизировать влияние ошибок на конечных пользователей и обеспечить постоянное функционирование системы.
Вам может быть интересно
Low-code дополняет разработчиков, автоматизируя рутинные задачи, сохраняя при этом их важную роль в архитектуре и решении сложных проблем.Распространение платформ low-code-разработки вызвало бурные де...
Развитие информационных технологий - ключевой фактор успеха в современном бизнес...
Выбор API играет ключевую роль в успехе и эффектив...
В современном обществе программирование становится...
В этой статье разработчики компании DST Global рас...
Мастерство, необходимое для создания производитель...
В мире есть много способов программирования. Но од...
Название PHP расшифровывается как гипертекстовый п...
Прежде чем мы узнаем для чего и как придумали объе...
Что такое программное обеспечение для разработки п...

Заявка на услуги DST

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

Адрес

Ижевск, ул. Воткинское шоссе 170 Е.
Региональный оператор Сколково. Технопарк Нобель

8 495 1985800
Заказать звонок

Режим работы: Пн-Пт 10:00-19:00

info@dstglobal.ru

Задать вопрос по почте

Укажите ваше имя
Укажите ваше email
Укажите ваше телефон