Мартин Клеппман (Martin Kleppman) – исследователь в Кембриджском университете, работающий над CRDT и формальной верификацией алгоритмов. Его книга «Designing Data-Intensive Applications», опубликованная в 2017 году, стала бестселлером в области хранения и обработки данных.
Kevin Scott (CTO в Microsoft) однажды сказал: «Эта книга должна быть обязательной для инженеров-разработчиков. Это редкий ресурс, объединяющий теорию и практику, помогающий разработчикам глубже продумывать дизайн и реализацию инфраструктуры и систем обработки данных». Что-то похожее говорил и Jay Kreps — создатель Apache Kafka и CEO Confluent.
А прежде чем заняться академическими исследованиями, Мартин работал в индустрии и стал сооснователем двух успешных стартапов: Rapportive (купленный LinkedIn в 2012 году) и Go Test It (куплен RedGate).
Этот хабрапост – развернутое интервью с Мартином. Примерные темы обсуждения:
- Переход от бизнеса к академическим исследованиям;
- Предпосылки написания Designing Data-Intensive Applications;
- Здравый смысл против искусственного ажиотажа и рекламы инструментов;
- Ненужность теоремы CAP и другие ошибки индустрии;
- Полезность децентрализации;
- Блокчейны, Dat, IPFS, Filecoin, WebRTC;
- Новые CRDT. Формальная верификация на Isabelle;
- Дискуссия про event sourcing. Низкоуровневый подход. XA-транзакции;
- Apache Kafka, PostgreSQL, Memcached, Redis, Elasticsearch;
- Использование всего этого в реальной жизни;
- Порог входа в доклады Мартина и конференция Hydra.
Интервью провёл Вадим Цесько (@incubos) — ведущий разработчик в команде Платформы компании Одноклассники. Научные и инженерные интересы Вадима касаются распределённых систем и хранилищ данных, а также верификации программных систем.
От бизнеса к академическим исследованиям
Вадим: Я хотел бы начать с вопроса, который очень важен для меня лично. Вы основали Go Test It и Rapportive, и в течение длительного времени занимались разработкой больших систем в LinkedIn, но потом решили уйти из коммерческой разработки и заняться исследованиями в университете. Не могли бы вы рассказать, что вас к этому толкнуло? В чем преимущества работы в университете, и чем вам пришлось пожертвовать?
Мартин: Это был очень интересный переход. Как я понимаю, мое решение интересует вас из-за того, что в академические исследования из коммерческой разработки уходит довольно мало людей, значительно чаще происходит движение в обратную сторону. Это вполне объяснимо, поскольку заработки в университетах существенно ниже, чем в бизнесе. Меня лично в позиции исследователя привлекает тот факт, что я могу сам решать, над какими темами мне работать, и я делаю этот выбор на основе того, что мне кажется интересным и важным, даже если работа над темой не обещает дать прибыль в течение следующих 6 месяцев. Все, над чем вы работаете в компании, должно в той или иной форме быть продано. В данный момент я работаю над важными для будущего интернета и ПО темами, но наше понимание их еще недостаточно глубоко, чтобы можно было создать готовый продукт. Пока что мы даже в общих чертах не представляем, как эти технологии должны работать. Поскольку эти исследования фундаментальные, я решил, что их лучше вести в университете, а не в компании: в университете больше свободы, там можно заниматься вещами, которые еще 10 лет не будут приносить никакой прибыли. Горизонт планирования значительно шире.
Книга «Designing Data-Intensive Applications»
Вадим: Мы обязательно вернемся к теме исследований, а пока давайте поговорим о вашей книге, Designing Data-Intensive Applications. На мой взгляд, это одно из лучших руководств по современным распределенным системам, почти энциклопедия: в ней перечислены все наиболее значимые достижения, существующие сегодня.
Мартин: Спасибо, я рад, что она вам пригодилась.
Вадим: Маловероятно, что наши читатели еще с ней не знакомы, но на всякий случай, давайте обсудим наиболее существенные достижения в области распределенных систем, о которых вы пишете.
Мартин: На самом деле, при написании этой книги я не ставил цели описать определенные технологии. Скорее я хотел сделать руководство по всему миру систем, используемых для хранения и обработки данных. Сейчас существует огромное количество баз данных, потоковых процессоров, инструментов пакетной обработки, всякого рода инструментов репликации и тому подобного, поэтому составить для себя общую картину этой области очень тяжело. И если нужна база данных для решения определенной проблемы, трудно выбрать какую-то одну из множества существующих. Многие написанные о таких системах книги в этом случае просто бесполезны. Например, в книге про Apache Cassandra может быть написано о том, какая Cassandra замечательная, но ничего не будет сказано о задачах, для которых она не подходит. Поэтому в своей книге я пытаюсь выявить основные вопросы, которые нужно себе задавать при написании больших систем. Ответы на эти вопросы помогут определить, какие технологии хорошо подходят для решения текущей проблемы, а какие — не очень. Главное, что не существует технологии, которая умела бы все. Я пытаюсь показать, в чем преимущества и недостатки разных технологий в разных контекстах.
Вадим: Действительно, многие технологии имеют общие черты и функциональность и предоставляют одну и ту же модель данных. При этом нельзя доверять рекламе, и чтобы разобраться во внутреннем устройстве системы приходится читать не только технические отчёты и документацию, но даже исходники.
Здравый смысл против искусственного ажиотажа и рекламы инструментов
Мартин: Больше того, зачастую приходится читать между строк, потому что в документации не написано, для каких задач база данных подходит не очень хорошо. На самом деле, любая база данных имеет свои ограничения, поэтому нужно всегда знать, какие именно. Зачастую приходится читать руководства по развертыванию и по ним реконструировать внутреннюю работу системы.
Вадим: Да, это отличный пример. Вам не кажется, что в этой области не хватает общего словаря или единого набора критериев, используя которые можно было бы сравнивать различные решения для одной задачи? Сейчас для одних и тех же вещей используются разные имена, а многие аспекты, которые должны быть четко и ясно прописаны, вовсе не упоминаются — например, гарантии транзакционности.
Мартин: Да, это действительно так. К сожалению, в нашей отрасли очень часто возникает излишний ажиотаж вокруг разных инструментов. Что вполне объяснимо, поскольку эти инструменты создаются компаниями, которые заинтересованы в продвижении своих продуктов. Поэтому эти компании отправляют людей на конференции, и те, в сущности, рассказывают о том, какие эти продукты замечательные. Это маскируется под технические доклады, но, в сущности, это реклама. Нам как отрасли совершенно не помешало бы быть более честными относительно достоинств и недостатков производимых нами продуктов. Одно из требований для этого — общая терминология, без нее сравнивать вещи невозможно. Но помимо этого необходимы способы анализа преимуществ и недостатков различных технологий.
Ненужность теоремы CAP и другие ошибки индустрии
Вадим: Мой следующий вопрос довольно щекотливый. Не могли бы вы рассказать о каких-нибудь общепринятых ошибках в нашей отрасли, с которыми вам пришлось столкнуться по ходу вашей карьеры? Например, о какой-нибудь переоцененной технологии или о широко используемом решении, от которого давным-давно следовало избавиться? Возможно, это не лучший пример, но мне приходит на ум использование JSON over HTTP/1.1 вместо gRPC over HTTP/2. Или быть может, вы не разделяете такую точку зрения?
Мартин: Чаще всего при создании систем, чтобы добиться чего-то одного, нужно пожертвовать чем-то другим, и тут я предпочитаю не говорить об ошибках. В случае с выбором между JSON over HTTP/1.1 и, скажем, Protocol Buffers over HTTP/2 оба варианта вполне имеют право на существование. Если принято решение использовать Protocol Buffers, необходимо определить схему, и она может быть очень полезной, поскольку она помогает точно определить поведение системы. Но в некоторых ситуациях ничего кроме раздражения такая схема не вызывает, в особенности на ранних этапах разработки, когда форматы данных меняются довольно часто. Опять-таки, здесь для достижения определенной цели приходится чем-то жертвовать, и в одних ситуациях это оправданно, а в других — нет. Решений, которые действительно можно назвать неправильными, на самом деле, не так уж и много. Но раз уж об этом зашла речь, давайте поговорим о теореме CAP — на мой взгляд, от нее нет совершенно никакой пользы. Когда ее используют при проектировании систем, то либо имеет место непонимание смысла теоремы CAP, либо при помощи неё обосновывают самоочевидные утверждения. В ней используется очень узко определённая модель согласованности — линеаризуемость, и очень узко определённая модель доступности — каждая реплика должна быть полностью доступна, даже если она не может установить связь с какой-либо другой репликой. С одной стороны, эти определения вполне верные, но, с другой, они слишком узкие: многим приложениям попросту не нужно именно такое определение согласованности или доступности. И если в приложении используется другое определение этих слов, теорема CAP для него бесполезна. Так что я не вижу большого смысла в её применении. Кстати говоря, коль скоро мы заговорили об ошибках в нашей отрасли, давайте честно признаемся, что майнинг криптовалют — совершенно бесцельная трата электричества. Я не понимаю, как этим можно всерьёз заниматься.
Вадим: Кроме того, большая часть технологий хранения данных сейчас настраиваемы под определенную задачу, т.е. можно выбрать подходящий режим работы в присутствии сбоев.
Мартин: Совершенно верно. Больше того, значительная часть технологий не подпадают под строгое определение согласованности и доступности теоремы СAP, то есть они не CP, не AP и не CA, а только P. Прямо это про свой софт никто не напишет, но на самом-то деле это может быть вполне рациональной стратегией при разработке. Это одна из причин, по которым я считаю, что от CAP при анализе софта больше вреда, чем пользы: значительная часть проектировочных решений в ней никак не представлены, причем это могут быть вполне рациональные решения, а CAP не позволяет их описать.
Полезность децентрализации
Вадим: Какие проблемы в разработке Data-Intensive Applications стоят сейчас наиболее остро? Какие темы наиболее активно исследуются? Насколько мне известно, вы являетесь сторонником децентрализованных вычислений и децентрализованных хранилищ данных.
Мартин: Да. Один из тезисов, которые я доказываю в своём исследовании, заключается в том, что в данный момент мы слишком сильно полагаемся на серверы и централизацию. В первое время существования интернета, когда он развивался из ARPANET, он проектировался как максимально устойчивая сеть, в которой пакеты можно отправлять по различным маршрутам, и они всё равно все достигают цели. В случае ядерного взрыва в каком-либо городе в Америке уцелевшая часть сети продолжала бы работать, просто использовались бы альтернативные маршруты в обход вышедших из строя участков. Это была схема, порождённая холодной войной. Но потом мы решили разместить всё в облаке, так что сейчас практически всё так или иначе проходит через один из центров AWS где-то в Вирджинии, на востоке США. В определенный момент мы отказались от идеала децентрализованного использования различных частей сети и выделили сервисы, от которых теперь всё зависит. Я считаю важным вновь вернуться к децентрализованному подходу, при котором больше контроля над данными принадлежало бы не сервисам, а конечным пользователям.
Когда речь заходит о децентрализации очень часто под этим понимают вещи вроде криптовалют, поскольку в них функционируют сети взаимодействующих агентов, над которыми нет единой централизованной власти вроде банка. Но это не та децентрализация, о которой говорю я, поскольку, на мой взгляд, криптовалюты тоже крайне централизованы: если необходимо выполнить сделку с Bitcoin, её обязательно нужно сделать через сеть Bitcoin, так что всё централизовано вокруг этой сети. Структура сети децентрализована в том смысле, что у нее нет единого организующего центра, но сеть в целом крайне централизована, поскольку каждая сделка должна совершаться через эту сеть и никак иначе. Я считаю, что это тоже форма централизации. В случае с криптовалютами это неизбежно, поскольку необходимо обеспечить отсутствие двойных расходов, а этого тяжело добиться без сети, которая обеспечивает консенсус относительно того, какие сделки были совершены, и тому подобного. Но есть множество приложений, которые не требуют системы вроде блокчейна, они могут работать со значительно более гибкой моделью данных. Именно такие децентрализованные системы интересуют меня больше всего.
Вадим: Коль скоро вы упомянули блокчейн, не могли бы вы рассказать о многообещающих или недостаточно известных технологиях в области децентрализованных систем? Сам я игрался с IPFS, но у вас гораздо больше опыта в этой сфере.
Мартин: На самом деле, я не слежу активно за такими технологиями. Я немного читал о IPFS, но сам ее не использовал. Мы немного работали с Dat, который, как и IPFS, является технологией децентрализованного хранения данных. Различие в том, что к IPFS привязана криптовалюта Filecoin, и она используется для оплаты хранения данных, а к Dat не привязан никакой блокчейн. Dat только позволяет реплицировать данные на несколько машин по принципу P2P, и для проекта, над которым мы работали, Dat отлично подходит. Мы писали ПО для совместной работы пользователей над документом, данными или базой данных, и каждое изменение в этих данных отправляется всем, у кого есть копия данных. В такой системе Dat можно использовать по принципу P2P, чтобы он обеспечивал работу на уровне сети, то есть NAT Traversal и прохождение через файрволы, что является довольно сложной задачей. Поверх этого мы написали уровень из CRDT, при помощи которых несколько людей могли редактировать документ или набор данных и которые позволяли быстро и удобно обмениваться правками. Думаю, аналогичную систему можно было написать и поверх IPFS, при этом игнорируя Filecoin и пользуясь только P2P репликацией.
Вадим: Но разве такая система не стала бы менее отзывчивой, ведь WebRTC напрямую соединяет узлы друг с другом, а IPFS — скорее распределенная хэш-таблица.
Мартин: Дело в том, что WebRTC — это несколько другой уровень стека. Он предназначен в основном для видеозвонков — с большой вероятностью он используется в том софте, через который мы с вами сейчас общаемся. Кроме того, WebRTC предоставляет канал, через который можно отправлять произвольные бинарные данные. Но создать поверх него систему репликации может быть трудно. А в Dat и IPFS для этого ничего делать не нужно.
Вы упомянули отзывчивость, и это действительно важный фактор, который необходимо иметь в виду. Предположим, мы хотим сделать следующий Google Docs децентрализованным. В Google Docs единица изменений — отдельное нажатие клавиши, и каждый новый символ может быть отправлен в реальном времени другим людям, которые работают с тем же документом. С одной стороны, это обеспечивает быструю совместную работу, с другой, это значит, что при написании крупного документа необходимо переслать сотни тысяч односимвольных изменений, и многие существующие технологии плохо справляются со сжатием такого рода данных. Даже если предположить, что для каждого нажатия клавиши необходимо отправить всего сотню байт, то для документа из 100 000 символов будет необходимо переслать 10 МБ данных, при том что обычно такой документ занимает не больше нескольких десятков килобайт. Пока не изобретен некий хитрый способ сжатия такая синхронизация данных требует колоссальной дополнительной затраты ресурсов. Во многих P2P системах пока нет эффективного способа создания моментальных снимков состояния, который позволил бы использовать их для системы вроде Google Docs. Именно этой проблемой я сейчас и занимаюсь, пытаюсь создать алгоритм для более эффективной синхронизации документа для нескольких пользователей. Это должен быть алгоритм, который позволил бы не хранить каждое отдельное нажатие клавиши, поскольку для этого нужно слишком много ресурсов, и он должен обеспечить более эффективное использование сети.
Новые CRDT, формальная верификация на Isabelle
Вадим: Вы не могли бы рассказать об этом подробнее? Удалось ли вам добиться более чем 100-кратного сжатия данных? Речь идёт о новых приёмах сжатия или специальных CRDT?
Мартин: Да. Пока что у нас есть только прототип, он еще не полностью реализован. Нужно поставить дополнительные эксперименты, чтобы узнать, насколько он эффективен на практике. Но некоторые из наших методов многообещающие. В моем прототипе мне удалось сократить размер одного редактирования со 100 до 1.7 байт. Но, повторюсь, это пока только экспериментальная версия, этот показатель может немного поменяться. Так или иначе, в этой области есть большие возможности для оптимизации.
Вадим: Значит, ваш доклад на конференции Hydra будет именно об этом?
Мартин: Да. У меня будет короткое введение о CRDT, софте для совместной работы и некоторых проблемах, которые возникают в этом контексте. Затем я расскажу об исследованиях, которые мы ведем в этой области — они касаются множества различных проблем. С прикладной стороны у нас есть реализация этих алгоритмов на JavaScript, на основе неё мы создаём функционирующие программы, чтобы лучше понять поведение алгоритмов. При этом мы также работаем над формальными методами доказательства правильности этих алгоритмов, потому что некоторые из них довольно неочевидные, а мы хотим добиться, чтобы они всегда достигали согласованного состояния. Многие разработанные ранее алгоритмы не обеспечивают согласованность в некоторых пограничных случаях. Чтобы этого избежать, мы обратились к формальным методам доказательства правильности.
Вадим: Используете ли вы для этого системы доказательства теорем вроде Coq или Isabelle?
Мартин: Да, Isabelle.
Примечание редакции: Мартин прочитает доклад про Isabelle на конференции The Strange Loop.
Вадим: Вы планируете опубликовать эти доказательства?
Мартин: Да, первый набор доказательств мы опубликовали полтора года назад вместе с фреймворком для проверки CRDT. Мы проверили три CRDT при помощи этого фреймворка, самый важный из них был RGA (Replicated Growable Array), CRDT для совместного редактирования текста. Этот алгоритм не слишком сложный, но довольно неочевидный, на взгляд не сразу понятно, корректный ли он, поэтому необходимо было формальное доказательство. Мы также занимались доказательством корректности нескольких существующих CRDT, а последнее, что мы делали в этой области — создание своих CRDT для новых моделей данных.
Вадим: Насколько объём формального доказательства больше чем размер кода самого алгоритма? С этим иногда возникают трудности.
Мартин: Трудностей действительно хватает, с доказательствами приходится много работать. Я сейчас посмотрел на код: описание алгоритма занимает около 60 строк, он довольно компактный, а доказательство превышает 800 строк. Получается, что доказательство в 12 раз длиннее. К сожалению, это вполне типичная ситуация. С другой стороны, наличие формального доказательства даёт нам уверенность в корректности алгоритма. Кроме того, работа над доказательством позволила нам самим лучше понять этот алгоритм. Формализация вообще этому часто способствует. В конечном итоге, это позволяет создавать более качественные реализации алгоритмов.
Вадим: Скажите, на какую аудиторию вы рассчитываете ваш доклад? Какие необходимы предварительные знания?
Мартин: Я стараюсь делать свои доклады как можно более доступными, и пытаюсь подтянуть всех до одного уровня. Я даю много материала, но начинаю с довольно простых вещей. Для слушателей будет полезно иметь некоторый опыт с распределенными системами: отправка данных по сети через TCP, представление об устройстве Git и тому подобное. Но, по большому счёту, помимо базовых знаний ничего не нужно. Имея их, понять нашу работу не так уж и трудно. Я объясняю всё на примерах и иллюстрирую их картинками. Надеюсь, что доклад будет доступен всем.
Event sourcing, низкоуровневый подход, XA-транзакции
Вадим: Я хотел бы поговорить о вашей недавней статье, посвящённой обработке событий онлайн. Насколько я понимаю, вы сторонник event sourcing. Сейчас этот подход обретает всё большую популярность, и программисты пытаются применять его везде из-за преимуществ глобально упорядоченного журнала операций. А в каких ситуациях event sourcing не самый лучший подход? Хотелось бы избежать разочарования в этой технологии из-за того, что люди пытаются применить её везде и в некоторых случаях она плохо работает.
Мартин: Эту проблему нужно обсудить на двух различных уровнях. Event sourcing в той форме, в какой его создал Грег Янг и другие, является механизмом моделирования данных. Если в вашей базе данных становится слишком много таблиц и транзакций с этими таблицами и она становится слишком неорганизованной, то event sourcing может помочь упорядочить модель данных. События могут выразить напрямую, что происходит на уровне логики приложения, какое действие предпринимает пользователь, как его последствия обновляют различные таблицы и так далее. В сущности, event sourcing позволяет отделить действие (событие) от его последствий.
Я пришёл к event sourcing с более низкоуровневой стороны. Я занимался созданием масштабируемых систем при помощи технологий вроде Apache Kafka. Event sourcing похож на Apache Kafka, поскольку и там, и там используются события. Но для event sourcing использовать Apache Kafka не обязательно, это можно делать и с помощью обычной базы данных, или базы данных, специально созданной для event sourcing. В общем, эти подходы похожи, но они не завязаны друг на друга, просто у них есть некоторое пересечение. Система вроде Apache Kafka полезна, если необходимо масштабирование, если поток данных настолько большой, что обработать их в базе данных, состоящей из одного узла, невозможно. При помощи журнала событий вроде Apache Kafka эту нагрузку можно распределить на несколько компьютеров. Apache Kafka особенно полезна, если необходимо интегрировать несколько различных систем хранения данных. При помощи неё можно обновить одним событием не только реляционную базу данных, но и полнотекстовый поисковый индекс вроде Elasticsearch, или систему кэширования вроде Memcached или Redis.
Что касается вашего изначального вопроса, то мне сложно точно сказать, когда именно не следует использовать event sourcing. Как правило, я предпочитаю использовать наиболее простой подход. Если необходимая модель данных прекрасно реализуется в реляционной базе данных со вставкой, обновлением и удалением строк, то используйте её. Реляционные базы данных — вполне допустимый вариант, они прекрасно нам служат уже давно. Но если модель данных становится слишком сложной для реляционной базы данных, то следует перейти к event sourcing. Аналогичного принципа следует придерживаться и на более низком уровне: если размер данных позволяет хранить их в PostgreSQL на одном компьютере, то так и следует поступить. Если же один компьютер не может обработать все данные, то следует обратиться к распределенным системам вроде Kafka. То есть, повторюсь, для каждой ситуации следует выбирать наиболее простой для нее подход.
Вадим: Это прекрасный совет. Кроме того, большинство прикладных систем постоянно развиваются и направление их развития не всегда известно заранее, так что никогда не знаешь наперёд, какие в них появятся запросы, паттерны и потоки данных.
Мартин: Да, и в этом отношении особенно полезны реляционные базы данных, потому что как правило сейчас у них есть поддержка JSON (например, PostgreSQL отлично его поддерживает) и с ней они особенно гибкие. Если необходимо поддержать новые запросы, можно просто создать недостающие индексы. Можно поменять схему данных и смигрировать базу. Если размер данных не слишком большой и они не слишком сложные, все будет прекрасно работать.
Вадим: У меня есть ещё один вопрос относительно event sourcing. Вы упомянули интересный пример, в котором события из одной очереди отправляются нескольким получателям. Предположим, у нас создаётся новый документ (скажем, объявление), и несколько систем получают о нём события: поисковая система на основе Elasticsearch, которая позволяет найти это объявление; система кэширования, которая помещает его в кэш key-value на основе Memcached; и база данных, которая сохраняет его в таблицы. Эти системы работают одновременно и параллельно.
Мартин: То есть вы хотите узнать, что делать, если некоторые из этих получателей событий уже обновлены, а другие — ещё нет?
Вадим: Да. И в этой ситуации на сайт приходит пользователь, вводит поисковый запрос и видит, что, скажем, в этом районе доступна квартира, но после клика по объявлению получает код 404, поскольку база данных ещё не успела получить событие и нужный документ в ней пока отсутствует.
Мартин: Это действительно существенная трудность. В идеале необходимо обеспечивать причинную согласованность (causal consitency) для этих систем. То есть если одна система содержит в себе некоторые необходимые данные, то они также будут находиться и в других системах. К сожалению, добиться этого для нескольких различных систем хранения данных очень трудно: не важно, какой используется подход или система для отправки обновлений различным системам, в конечном итоге всегда могут возникнуть проблемы с параллелизмом. Даже если выполнять запись в обе системы одновременно, может возникнуть небольшая задержка в сети, из-за которой обработка одного из действий записи произойдет немного раньше или позже. При чтении из обеих систем может быть выявлена несогласованность. Существуют исследовательские проекты, которые пытаются добиться такого рода причинной согласованности, но её сложно обеспечить, просто используя Elasticsearch или Memcached. Проблема в том, что для правильного решения здесь необходимо иметь моментальный снимок и поискового индекса, и кэша, и базы данных. Если мы работаем только с реляционной базой данных, то у нас возникает snapshot isolation: это значит, что чтение из базы данных выполняется так, как будто бы у вас есть копия всей базы данных. И все запросы будут возвращать данные на момент создания снимка. То есть даже если данные на момент чтения изменились, будут всё равно представлены старые данные, потому что они являются частью согласованного моментального снимка. В обсуждаемом случае с Memcached и Elasticsearch проблему можно решить при помощи согласованного моментального снимка этих двух систем. Но, к сожалению, ни Memcached, ни Redis, ни Elasticsearch не предоставляют эффективного механизма создания таких снимков, которые можно было бы координировать для нескольких систем хранения данных. Каждая система действует самостоятельно и, как правило, просто выдаёт последнее значение каждого ключа. Возможности получить более раннюю, но согласованную версию данных обычно нет. Так что я не могу порекомендовать оптимального решения для этой проблемы. Боюсь, что так или иначе придётся менять код систем хранения данных. Нужен механизм создания моментальных снимков, который был бы достаточно быстрым, чтобы им можно было постоянно пользоваться — такие снимки могут быть необходимы несколько раз в секунду, а не один раз в день. Пока что существующие решения не позволяют создавать моментальные снимки для нескольких систем хранения данных. В целом, это очень интересная исследовательская тема. Надеюсь, что кто-то ею займётся, но пока что удовлетворительного решения этой проблемы я не видел.
Вадим: Да, необходим некий единый распределенный Multiversion Concurrency Control.
Мартин: Да, наподобие систем распределенных транзакций. Можно использовать распределенные XA-транзакции, но, к сожалению, в текущем состоянии эта система не очень хорошо подходит для этих целей. Она работает только с контролем параллелизма на основе блокировок, то есть при чтении любых данных эти данные блокируются, и никто другой не может их изменить. Дело в том, что такой параллелизм имеет очень низкую производительность, поэтому на практике он сейчас не применяется. Но без такой блокировки создать моментальные снимки в XA невозможно. Быть может, из этого затруднения мог бы вывести новый протокол для распределенных транзакций, который позволял бы использовать изоляцию моментальных снимков для нескольких различных систем. Но пока я ничего подобного не видел.
Вадим: Будем надеяться, что кто-то над этим работает.
Мартин: Это было бы очень полезно, в том числе для микросервисов. Сейчас считается правильным создавать для каждого микросервиса своё хранилище, свою базу данных, и микросервис не должен обращаться напрямую к базе данных другого сервиса, поскольку это было бы нарушением инкапсуляции. Каждый сервис управляет только своими данными, и существует отдельный сервис для управления пользователями с отдельной базой данных. Если необходимо что-либо узнать о пользователях, нужно обратиться к этому сервису. Всё это позволяет соблюсти инкапсуляцию, поскольку при этом подходе подробности схемы базы данных скрыты от других сервисов. Но это создаёт большие трудности с соблюдением согласованности различных сервисов между собой из-за проблемы, которую мы только что обсуждали: в двух сервисах могут быть данные, зависящие друг от друга, и в одном из этих сервисов они могут оказаться обновлены немного раньше, чем в другом. Тогда при чтении из этих двух сервисов будут получены несогласованные результаты. Насколько я знаю, адекватного решения этой проблемы для микросервисов пока не существует.
Вадим: Меня вдруг посетила мысль, что в обществе и в государстве рабочие процессы устроены весьма похожим образом. Они по сути своей асинхронны, и в них отсутствуют гарантии доставки. Если кто-то поменял свой номер паспорта, ему необходимо доказать, что он это сделал, и что он по-прежнему является той же личностью.
Мартин: Совершенно верно. Но в обществе мы умеем находить решение для этих проблем. Мы можем определить, что информация в некоторой базе данных устарела, и тогда мы просто повторяем запрос в другой день. Но при написании софта все эти механизмы необходимо специально создавать, потому что софт сам не мыслит.
Вадим: По крайней мере, пока не мыслит. Я хотел бы ещё поговорить о преимуществах event sourcing. При использовании этого подхода можно остановить обработку событий, если обнаружен баг, и возобновить обработку, когда развёрнута новая версия с исправлением. Таким образом, система всегда находится в согласованном состоянии. Это очень полезная и востребованная возможность, но в случае, например, банковского софта ей пользоваться невозможно. Предположим, в банке работает система, которая продолжает получать финансовые транзакции, но при этом балансы или остатки являются устаревшими, поскольку приостановлено получение событий до тех пор, пока не развёрнута новая версия без бага. Как избежать такой ситуации?
Мартин: Я не думаю, что в реальности для развёртывания новой версии приостанавливается работа системы. Скорее в случае бага система продолжает работать, и параллельно с ней создаётся новая версия кода без бага, которая затем запускается параллельно со старой. Исправленная версия должна будет обработать все входящие события, произошедшие с момента развёртывания кода с багом, и, возможно, записать результат в отдельную базу данных. После этого можно произвести замену и отключить старую версию. Таким образом, система ни в какой момент не прекращает работу. Благодаря этому у разработчиков есть время исправить баг, и они могут устранить его последствия, поскольку можно повторно обработать входные события.
Вадим: Да, это отличный подход в случае, если есть контроль над хранилищем, но здесь не учитываются побочные эффекты для внешних систем.
Мартин: Это верно. Если данные отправлены сторонней системе, исправить их может быть невозможно. Но это та же ситуация, с которой сталкиваются в бухгалтерском учёте. Когда создаётся квартальный отчёт, фиксируется состояние всех сделок на конец квартала, доход и прибыль рассчитываются, опираясь на эти показатели. Но иногда данные о некоторых транзакциях приходят с запозданием (скажем, кто-то забыл отдать квитанцию), хоть сама транзакция и относится к предыдущему кварталу. В этом случае бухгалтеры учитывают её в следующем квартале как поправку к предыдущему. Обычно такие изменения составляют незначительную сумму и никаких ошибок из-за этого не возникает, при этом в конечном итоге учитывается правильная сумма. В бухгалтерском учёте этот подход применяется столетиями — столько, сколько существует сам бухгалтерский учёт. Думаю, мы можем перенять этот опыт и применить тот же подход для других типов систем хранения данных, то есть нам нужно признать, что цифры в основном верны, но не на 100%, точные цифры могут стать известны лишь позднее.
Вадим: Интересно. Это новый подход к написанию систем.
Примечание редакции: Год назад Владимир Красильщик про это делал доклад.
Мартин: Да, это не вполне обычный взгляд на вещи, и на первый взгляд он может приводить в замешательство. Но я боюсь, что другого пути нет — наше знание о всём состоянии мира неизбежно неточное, при работе с распределёнными системами от этого никуда не уйти. И эта неточность обязательно вскрывается при обработке данных.
Конференция Hydra 2019, профессиональный рост и развитие
Вадим: Как вам кажется, насколько важны конференции вроде Hydra? Ведь все распределённые системы очень разные, и мне сложно представить, что все участники после конференции сразу начнут применять на практике новые подходы, о которых они узнали.
Мартин: Тема действительно широкая, но, на мой взгляд, значительная часть интересных подходов в области распределенных систем относятся скорее к концептуальному уровню, то есть это не прямые указания «используй эту базу данных» или «используй эту технологию». Скорее речь идёт о способах мышления о системах и о софте. Такого рода идеи могут иметь довольно широкое применение. Если честно, мне не так уж и важно, узнают ли участники о каком-то новом языке или инструменте; значительно важнее, на мой взгляд, чтобы они узнали о том, как мыслить о системах, которые они создают.
Вадим: Если речь идёт о настолько сложных темах, как та, которую вы будете обсуждать в своём докладе, то в чём преимущество докладов на конференции перед публикацией в научном журнале? Ведь во втором случае можно значительно более подробно осветить тему. Или вы считаете, что необходимо делать и то, и другое?
Мартин: Я думаю, что публикации и доклады преследуют разные цели. В публикации можно очень подробно, точно и достоверно проанализировать проблему. Доклад скорее служит для того, чтобы заинтересовать этой темой других людей и инициировать дискуссию. Мне нравится посещать конференции отчасти именно из-за обсуждений после докладов. Ко мне постоянно подходят люди из аудитории и говорят, что они что-то подобное уже пробовали, но при этом наткнулись на такие-то проблемы. И размышляя над их проблемами, я сам узнаю для себя много нового. Для меня это важная причина выступать на конференциях: я учусь на опыте других людей и делюсь своим опытом, если он полезен другим людям. Но в основе своей выступление на конференции — скорее введение в проблему, а публикация — глубокий анализ довольно узкого вопроса. Так что, на мой взгляд, это очень разные жанры, и нам нужны они оба.
Вадим: И последний вопрос. Что вы делаете для своего профессионального роста как исследователя и разработчика? Возможно, вы могли бы порекомендовать какие-либо конференции, блоги или сообщества для тех, кто хочет развиваться в области распределённых систем?
Мартин: Отличный вопрос. Интересных материалов есть множество. Например, в онлайне выложено много записей выступлений на конференциях. В книгах, в том числе в моей, можно найти как введение в тему, так и ссылки на другие исследования для дальнейшего чтения. Если возникают какие-то вопросы — можно пройти по ссылкам. Но помимо этого очень важно также самостоятельно писать системы и смотреть на практике, как они работают, а также делиться опытом с другими людьми. Отчасти именно этим полезны конференции: живым общением. Но общаться можно и другими способами, например, в Slack есть канал для людей, которым интересны распределённые системы. Наконец, вам ничто не мешает перенимать опыт у коллег в компании, где вы работаете. В общем, единственно правильного способа учиться не существует, нужно выбирать тот, который лучше подходит именно вам.
Вадим: Спасибо большое за ценные советы и интересную дискуссию.
Мартин: Пожалуйста, очень рад был с вами побеседовать.
Вадим: Отлично, тогда до встречи на конференции!
Напоминаю, что это предварительно записанное интервью. Когда вы будете писать комментарии — помните, что Мартин их не прочитает. Мы можем только передать что-то самое интересное. Если вам действительно хочется пообщаться с автором, то он будет с докладом «Syncing data across user devices for distributed collaboration» на конференции Hydra 2019, которая пройдёт 11-12 июля 2019 года в Санкт-Петербурге. Билеты можно приобрести на официальном сайте.
IRainman
Очень хорошее интервью. На тему, как я это называю «точности результата» это реально очень нужная штука. Когда, примерно в 2009 я начинал делать сложную распределённую систему, которая ещё и сама себя могла модифицировать в плане алгоритмов, то очень быстро пришёл к мысли что необходим параметр точность, т. е. явное ограничение достаточной точности (погрешности) для того чтобы считать результат модификации алгоритмов или построенной модели применимым. К сожалению, это не абсолютно везде работает, но для подавляющего большинства вычислений это подходит. Ещё в системе введён набор логических состояний, часть из которых откладывают дальнейшие действия, например, если не удалось выстроить весь граф зависимостей, то генерируется ошибка и система откладывает все дальнейшие работы с данными и алгоритмами зависящими от блоков с подобными ошибками. Самая большая проблема с таким подходом: сложность реализации систем с малыми задержками, но зато с точки зрения эффективности и при решении долгосрочных и длительных по времени выполнения задач это позволяет делать очень классные вещи.