Автор выражает благодарность людям, которые помогли в написании статьи:  И в особенности Махешу Балакришнану, к числу почитателей которого я присоединился:  Какая программа может решить проблему остановки в общем виде? Что поможет сделать успешный стартап по созданию убийцы гугла с бюджетом $100k? Что позволит реализовать масштабируемую систему на микросервисах быстрее и дешевле, чем монолит? Какая БД позволяет обеспечить сразу три гарантии теоремы CAP? Что позволит удовлетворить типичные взаимно противоречащие требования от клиента? Знакомьтесь: Ничто — самый востребованный продукт на рынке IT, и в условиях короновируса возник острый дефицит кадров, способных делать ничего. Вы не умеете ничего делать? Тогда вы в пролёте, рынку нужны люди, которые умеют делать ничего. Рынок нуждается в людях с богатым коммерческим опытом успешной реализации ничего и хорошей репутацией, со стабильным отсутствием оригинальных идей, которое они способны предложить ищущим стабильности в условиях постоянно меняющегося рынка. Этот спрос не безоснователен: ничто изначально имеет серьезное конкурентное проимущество над многими альтернативными решениями, ведь, как правило, ничто не требует большого объема ресурсов на реализацию. В каком-то смысле вероучение Agile идет рука об руку с другими религиями и с ничем, поскольку имеют своей целью не какие-то там малопонятные технические штуки, а простую удовлетворенность человека (заказчика и исполнителя). Как там говорят заповеди Agile: "Customer satisfaction by early and continuous delivery of valuable software". Позитивный настрой — это главная фича моего ничего, то настроение, с которым я доставляю свой софт, и та ценность, с которой я его преподношу, значит больше, чем сам софт. У чего-то есть недостатки, но у ничего смысла столько же, сколько во мне самом — вот она, свобода творца выбирать свой мир. "Куда идем мы с пятачком? Большой большой секрет. А смысл жизни нашей в чем? А смысла в жизни нет". Культура Индии, одной из старейших цивилизаций Земли, тесно переплетена с религией и давным-давно пришла к тому, что нет никакого "совершенствования" и "развития": нет развития, потому что вне человека нет цели для развития и нет объективных критериев развитости (с точки зрения амёбы клетки человека намного примитивнее); нет совершенствования, потому что совершенство — это смерть, неизменяемое совершенное состояние материи. Однако же, мы можем из ничего выдумать цели, критерии развития, что в русском фольклоре называется "не было у бабы хлопот, так купила баба порося". Что такое современная глобальная экономика? Идущая вразнос система, направленная на максимизацию выработки отходов и преумножения несчастья субъектов экономики для того, чтобы убедить их производить больше отходов и таким образом осчастливиться. Но вы же не скажете, что покупаете айфон для того, чтобы создать больше мусора на земле? Нет, вы скажете что-то вроде "я хочу выразить свою индивидуальность", или какую-то другую бессмыслицу, вроде "этим устройством удобно пользоваться". Объективное сравнение с другими вариантами никого не волнует, поскольку такая жизнь была бы скучна, да и, к тому же, никакой объективности не существует — лучше то, что я считаю лучшим. Индусы одними из первых сообразили, как коммерциализировать невидимое и неощущаемое, торговать желаниями, задолго до иудеев и христиан. Более того, воображаемые вещи могут стать более ценными, чем ощущаемые вещи, а эфемерное чудо тысячами лет притягивает своим таинством человека, уставшего от обыденности бытия. В прошлой статье я наплевал на опыт тысячелетий и наивно высказал глупость, смысл которой очень упрощенно такой: ничто не может быть лучше ZooKeeper. Да, признаю: ничто может быть лучше ZooKeeper. По крайней мере, разработав ничто можно сделать что-то новое, а оставаясь с ZooKeeper вы будете иметь старую унылую систему, которая просто работает. Бизнес хочет выше, быстрее, сильнее, хотя бы по сравнению с конкурентами, и ваша обязанность, как программиста и архитектора — эту потребность удовлетворить. Клиент думает, что ему для процветания бизнеса ничего не нужно? Ваша задача — убедить, что без ничего он не сможет прожить и дня. И для этого нужно прежде всего убедить себя в том, то ваше ничто кому-то нужно. Когда владельцу бизнеса/продукта ничего не нужно масштабировать, то ваша задача — убедить его, что ничто обязательно должно быть смасштабировано на Kafka, Hadoop, и микросервисах. От такой реализации будут довольны все, как показывает практический опыт. Теперь вы примерно начинаете догадываться, почему индус стал руководителем Microsoft — мудрость поколений, въевшуюся в гены, не пропьешь, никакой Гейтс или Балмер не годятся в подмётки Сатье. Как некоторые из вас знают, не так давно Facebook решил поручить моему гуру, опытному исследователю Махешу Балакришнан, перевод своей инфраструктуры с ZooKeeper на новое кастомное решение. Изначально задание было поставлено примерно такое: Rethinking monolithic system design Высокая производительность, отказоустойчивость, строгая согласованность данных, при этом с потенциальной поддержкой разных уровней согласованности данных и отказоустойчивости, неограниченная гибкость формы данных и API — и всё это должно быть выкачено в прод за несколько месяцев. Это идеальное задание для разработки Ничего: Virtual Consensus in Delos. Детали реализации вы можете прочитать в самой статье — я сделаю лишь краткий обзор ключевых свойств и назначения этой системы.  Слой материализации данных (Database в статье) — фиговина, которая применяет операции из распределенного лога к локальной копии данных, то есть, формирует видимые извне данные. Первая крупная БД подобного типа, Google Chubby, всем своим интерфейсом предписывала применение иерархичной структуры из мелких файлов, запись их содержимого только атомарно и целиком, то есть, оптимизацию под хранение управляющих структур, а не самих данных. Что нам предлагает Delos в качестве низкоуровневого интерфейса? Правильно — ничего, то есть, свободу выбора и позитивный взгляд в будущее: Delos: Simple, flexible storage for the Facebook control plane Пессимистичные душнилы скажут "да что же вы не можете наконец определиться с низкоуровневым представлением данных, и называете это фичей?" — но мы их не слушаем, они сами выбрали себе ярмо на шею. Душнила бы сказал, что при желании можно реализовать O(N^2) составные транзакции над табличками и на ZooKeeper, но для чего будет приемлема такая нагрузка на ключевую БД всей инфраструктуры Facebook? Правильно — для ничего, а это и является нашей основной целью разработки, не забываем. VirtualLog с MetaStore — это распределенный отказоустойчивый роутер, который знает, какой из логлетов (хранилище логов) содержит самые последние изменения и доступен на запись, а в каких логлетах архивные транзакции доступны лишь на чтение. VirtualLog роутит запросы append/readNext (запись/чтение) таким образом, что все логи из логлетов выглядят конкатенированными, а доступный на запись активный логлет находится в хвосте этого конкатенированного лога. MetaStore — это атомарный распределенный счетчик, в котором записан ID активного логлета (commit ID, но это не важно), то есть, MetaStore — основной механизм координации экземпляров VirtualStore-роутера. Поскольку этот счетчик меняется только при отказах, то его реализовали простым медленным Paxos. Delos: Simple, flexible storage for the Facebook control plane Сразу упреждая вопрос "а что же в этой системе нам позволит перейти от VirtualLog к прямому соединению с ZooKeeper или на другую БД?". Вы уже догадались — ничто, оно всегда приходит на помощь в трудную минуту. Посмотрим на устройство NativeLoglet, раздел 4.2.1. Как вы можете заметить, это по сути репликация ZAB/Raft в комбинации с ничем в роли механизма обнаружения отказов и возобновления работы — операцией seal, которая навсегда запечатывает логлет, переводя его в режим "только чтение". Обнаружение отказов находится в неопределенном месте вне системы, при отказе текущий логлет запечатывается и запись переводится на другой логлет (забегая вперед — ZooKeeper). 3.2. VirtualLog design Как вы можете увидеть, на более высоком уровне в качестве механизмов обнаружения отказов используется модифицированный вариант ничего — непонятно что, работающее по неясным алгоритмам. Последняя цитата по сути означает, что при срабатывании непонятно чего VirtualLog переключает хранение логов на ZooKeeper, поскольку NativeLoglet, как упомянуто выше, не способен работать в условиях систематических сбоев. Надо заметить, что наш любимый Яндекс долгое время тоже применял непонятно что в качестве механизма реакции на отказы, но на полпути сдрейфил и начал использовать ZooKeeper для всех задач координации. Одно из заявленных достижений проекта Delos — уменьшение времени ответа БД. Мой гуру безупречно реализует это ничто, за ширмой оно выглядит так: берется, ZooKeeper, поверх него строится слой трансляции (ZKLoglet), проводится нагрузочное тестирование ZKLoglet против NativeLoglet — NativeLoglet отвечает в 10 раз быстрее. Эту безупречную картину портят мерзкие душнилы-соавторы статьи, раздел 5.1 The Benefit of Virtualization: То есть, они хотят сказать, что время ответа у Delos такое же, как у прямого доступа к ZooKeeper. Ну как с такими работать? Жирную точку в архитектуре ставит абзац "ZooKeeper over Delos… over ZooKeeper" раздела 6 Discussion, где архитектура системы становится примерно такой:  Как вы понимаете, я признал Махеша своим гуру не за один единственный проект. У Махеша есть публикация на ту тему, которая мне очень близка, поскольку подобную цель я преследовал в Python Shared Objects — создание универсального механизма параллелизации алгоритмов. Эта публикация получила Best Paper Award, став кульминацией многих лет совершенствования навыка созидания ничего. Суть алгоритма заключается в том, что вместо классического поочередного выполнения операций непосредственно над общей памятью под глобальной RW блокировкой автор предлагает каждому NUMA-узлу иметь независимую (приватную) копию "общих данных", а пересылать между NUMA-узлами только команды по изменению этих данных через лог в разделяемой памяти, чтобы каждый NUMA-узел уже на приватной копии данных строго последовательно выполнял эти операции из лога. То есть, общаемся между NUMA-узлами не через общие данные, а через общий лог операций. Добавление пишущих операций в лог очевидно просто: зарезервировать диапазон ячеек в конце лога через атомарный счетчик, записать содержимое в ячейки этого блока. Но и такой алгоритм работы с логом был бы неэффективен на NUMA-системе. потому гуру сделал оптимизацию — сбор операций с нескольких потоков NUMA-узла в одну пачку, чтобы таким образом уменьшить число запросов между NUMA-узлами. Гуру адвокатирует flat combining для организации пакетирования, хотя здесь мог быть использован совершенно любой механизм блокировок в рамках одного NUMA-узла. Вторая оптимизация (раздел 5.4) — операции чтения, которые выполняются на приватной копии данных без взаимодействия с другими NUMA-узлами, читатель лишь по необходимости проматывает локальную копию до последнего корректного элемента общего лога, видимого при начале работы читателя, то есть, выполняет над локальными данными все известные операции из лога. Таким образом получается что-то между read committed и snapshot isolation, с вытекающими проблемами в виде чтения старых значений. Предлагаемый алгоритм по сути является NUMA-aware аналогом RW-блокировки: операции записи глобально сериализованы, операции чтения независимы. Забавно, что соавтор этой статьи, Irina Calciu, также являлась соавтором статьи моего любимого Нир Шавита: NUMA-Aware Reader-Writer Locks. В связи с чем передаю Ирочке пламенный поцелуй, а Нир Шавит пусть лучше старается — авось тогда и его кто-то заметит, кроме меня. Да, предлагаемое моим гуру ничто на немногочисленных сравнениях с lock-free алгоритмами (и с STM, на самом деле) показывает примерно никакую масштабируемость. Но давайте не забывать, что самое главное в проектировании ничего — это позитивный настрой и удовлетворенность клиента. Потому ничто нужно сравнивать с ничем, то есть, c простыми алгоритмами без поддержки NUMA. Самое выдающееся достижение моего гуру в данной статье — это, конечно же, заявка на ускорение Redis дописыванием всего-лишь 20 строчек кода в исходники Redis для интеграции новой библиотеки. Да, эти 20 строчек кода вводят поддержку многопоточности лишь в две из сотен доступных в Redis команд, а также в бенчмарках гуру применил ничто в качестве сетевого интерфейса (поскольку иначе сеть бы занимала большую часть времени обработки команд). Но заявка красивейшая ведь, согласитесь, Best Paper Award она получила заслужено за подачу RW-блокировки под видом универсальной lock-free конструкции, а вы уже захотели скачать патчи на Redis с поддержкой этой многопоточности, и даже захотели что-то подобное реализовать для своей софтины. Помним: удовлетворенность хотелок клиент — высший смысл разработки софта. Но это всё мелочи. Самые ценные советы я приберег напоследок... Да, вы можете душнить по технической части, мол "советы слишком общие" или "слишком конкретные и относятся только к его проекту", но давайте вспомним, что перед нами гуру разработки ничего, и именно в этом ключе его советы бесценны. Всегда понимайте, что продавая ничего вы должны удовлетворить хотелки заказчика, а не выдать эффективное решение. Потому мнение душнил-исполнителей никого не волнует, а взаимоисключающие требования заказчика подлажат тщательной интерпретации. Ничто должно иметь больше позитива в своем фундаменте. Мы не знаем что делаем, но мы точно знаем, какую реакцию руководства хотим получить — она может быть только позитивной. Даже если это руководство меняется. Особенно для достижения этой цели важно иметь единомышленников среди исполнителей и даже в соседних проектах. И боже упаси, чтобы отдельный исполнитель в вашей команде перестал делать ничего и ударился в какую-то техническую прагматику, за этим всегда нужно следить. Помните: никогда не используйте объективную метрику для оценки проекта. Удовлетворенность заказчика является единственной метрикой успешности. Перевод: лучше моего проекта не может быть ничего, поскольку им занимаюсь я. Даже если у вашего ничего всплыли какие-то проблемы в проде — заказчик должен быть последним, кто об этом узнает. Даже если ты сам последние 6 лет в четырех разных проектах с минимальными изменениями и завидным упрямством реализуешь те же самые алгоритмы и структуры данных — говори, что постоянно ищешь что-то новое. Разработка ничего заключается в том, что мы говорим и какие эмоции в людях это вызывает, а не в том, что может сделать полученная вещь. И помните: люди, которые не разбираются в вашей предметной области — это ваши ценнейшие союзники. Возможно ли разработать некую распределенную БД или систему координации так, чтобы она была расширяемой, простой в использовании, и при этом сама что-то из себя представляла, а не только очередную прокладку из ничего? Да, но это подразумевает смену парадигмы, как то отход от императивных операций над реляционными структурами: императивные операции над состоянием подразумевают строго пошаговое выполнение, что крайне плохо натягивается на многозадачность и распределенность; реляционные таблички подразумевают требование строгой согласованности между данными, что, опять же, плохо параллелится и распределяется. По этой причине, например, вы можете увидеть такой рост популярности key-value и прочих NoSQL решений. Однако, по большей части это стремление к смене парадигмы ограничивается специализированными решениями для конкретной задачи, то есть, серьезной потерей гибкости и функциональности — это же относится ко многим параллелизуемым/распределенным key-value БД, которые поддерживают либо очень простые, либо специализированные операции. Я уверен, что в Facebook прекрасно понимают существование этой проблемы, а также понимают, что, в нынешних условиях сокращения финансирования, ничто — это лучшее решение данной проблемы. Надеюсь, вам это понимание тоже поможет в вашем бизнесе. Программист