вторник, 24 июля 2018 г.

Как написать свою ОС?

Как я уже писал, материалов по поводу написания своей (хотя б маленькой учебной) СУБД в сети маловато. А вот руководств по созданию ОС - предостаточно.

Вбиваем в Гугл "how to write an operating system" (в подсказках еще "simple operating system source code" всплывает, но это потом посмотрю). И находим массу интересных текстов. 

Скажем, вот неплохая пдфка - Writing a Simple Operating System from Scratch. Кратко описано написание загрузочного сектора в 16-битном режиме, в 32-битном защищённом режиме; написание драйверов, файловой системы, создание ядра. 

Вот  гит-книжка How to Make a Computer Operating System. А вот The little book about OS development (по аналогии с "маленькими книжками" о Redis и Mongo). Разлюли-малина. Почему ж тему написания СУБД так обделили?

суббота, 21 июля 2018 г.

Thrift, Avro и Protobuf

Ссылка за ссылкой - двигаюсь по просторам Интернета, нахожу новую информацию.

В замечательном блоге eax.me нашел упоминание о книге Designing Data-Intensive Applications за авторством Мартина Клеппманна. Блоггер отозвался о книге положительно, посоветовал подписаться на журнал Мартина.

Ну а в блоге Клеппманна обнаружилась хорошая статья, где сравниваются форматы Thrift, Avro и Protobuf. Будет время - почитаю, очень хочется в этой теме разобраться.  

GDB

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

Можно почитать быстрый старт, а можно - подробную документацию.

пятница, 20 июля 2018 г.

Крамер и Маги: Concurrency

Нашел еще одну книгу по теории распределенных систем двух Джеффов: Concurrency: State models & Java programs (Jeff Magee, Jeff Kramer). По ней есть хорошая презентация Software Architecture: Modeling and Analysis, rigourous approach.   Таким образом, Джеффы подходят к вопросу с точки зрения моделирования, а не, скажем, отладки распределенных программ.

воскресенье, 15 июля 2018 г.

Классификации СУБД

Некто Себастьян Меньер в своем посте 2016 года привел очень хорошую, наглядную классификацию распределенных СУБД, в которую поместил в том числе и новомодный блокчейн.

А вот еще методичка по распределенным СУБД, в которой объясняется, чем отличаются между собой параллельные, сетевые и распределенные СУБД. А также есть еще масса интересной информации по распределенным СУБД.

Почему стоит писать СУБД?

Я уже упоминал статью Тома Кроули "Never Write Your Own Database". Так почему не стоит писать СУБД? А просто потому, что это очень сложное ПО, достаточно взглянуть на схему в моем предыдущем посте.

А почему, тем не менее, так много новых СУБД?  Во-первых, в "больших" СУБД масса возможностей, которые многим пользователям не нужны ("Wow, there’s a lot of stuff there that I don’t need. I wonder what I’m paying for that?"). Поэтому новая СУБД, в которой меньше лишнего, может оказаться востребованной. А во-вторых, СУБД, заточенная под какую-то конкретную задачу оказывается эффективней (в своей области), чем СУБД общего назначения.

Архитектура реляционной СУБД

О внутреннем устройстве СУБД информации не так уж и много. Но вот обнаружилась замечательная статья "Architecture of a Database System", где обозначен недостаток структурированных текстов на эту тему ("for a number of reasons, the lessons of database systems architecture are not as broadly known as they should be") и предпринята попытка дать развернутое описание темы. Один из авторов, кстати, - Майкл Стоунбрейкер, спец по эксплуатации БД на многопроцессорных машинах.

Статья большая (119 стр) и подробная. Но я здесь хочу привести из неё только схему, на которой отражены основные компоненты СУБД (щёлкните, чтоб увеличить) : 


Собственно, вот. Можно отталкиваться от этой картинки - и начинать погружение в архитектуру СУБД. Помня при этом правило "никогда не пишите свою СУБД".

пятница, 13 июля 2018 г.

Как написать свою СУБД?

Именно такой запрос я вбил в Гугл - "how to write a simple database program". И нашёл не так уж много информации.

В статье на Quora просто описали схему. Парсер разбирает запрос, создает дерево на основе реляционной алгебры. Далее при обработке запроса это дерево нужно будет рекурсивно обойти. Для ускорения поиска по БД нужны индексы. Для реализации индексов чаще всего используют хэш-таблицы и деревья. Существуют статические индексы, которые не меняются при добавлении/удалении/модификации данных (примеры - StaticHash и ISAM),
а также динамические, которые, соответственно, меняются при упомянутых операциях (примеры - DynamicHash и B-деревья).

В обсуждении на Stackexchange советуют учить матчасть, изучать исходный код открытых СУБД (таких как redis, flockdb и RavenDB), а также дают ссылки на книжки.

А потом оказалось, что среди разработчиков есть пословица (adage), которая звучит так "never write your own database". Именно такое название дал некто Терри Кроули своей статье. И объяснил, почему при работе над OneNote он с соратниками это правило нарушил.  Терри говорит:писать СУБД - дело крайне непростое, почитайте, говорит, хотя бы статью в Вики про ESENT.  Но если говорить об эффективности.... 

Кстати, а не почитать ли про ESENT?

вторник, 10 июля 2018 г.

Распределенные системы - схематично

Нашел  статью на tech.willhaben.at,  где хорошо выделили некоторые моменты теории распределенных систем. Приведу здесь эту информацию тезисно.

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

Распределенная система может создаваться по разным причинам:
  1. балансировка нагрузки
  2. горячее резервирование (hot standby)
  3. у каждого узла может быть своя задача
Сделать архитектуру ведущий-ведомые проще, чем абсолютно распределенную (когда все  узлы равноправны). У нас могут быть пакетные задачи (batch jobs), скажем, чистка БД, которые лучше выделить для одного узла - скорее всего, это будет мастер.

Некоторые вопросы, которые возникают в такой архитектуре:
  •     Как выбирать лидера?
  •     Что делать, если лидер упал? (автоматич отказоустойчивость) 
  •     Что будет, если лидер отключится от других сервисов?
  •     Что случится, если он переподключится? 
  •     Что делать, если лидер не отвечает?
 Все эти вопросы лучше не решать с нуля. В упомянутой статье рекомендуется использовать Apache Zookeeper. Это некий фреймворк, который умеет решать типовые проблемы распределенных систем. Например, именование, конфигурирование и синхронизацию сервисов (service synchronization). Кстати, а в чем состоит проблема именования? Об этом ниже.

Если коротко, Zookeper предлагает концепцию узлов. Каждому физическому узлу соотвествует узел зукипера со своим уникальным идентификатором. Как только физич узел системы отключается (или падает) - соответствующий ему узел зукипера исчезает. Таким образом, выбрать лидера очень просто - берется физич узел, которому соответствует узел зукипера с минимальным идентификатором.

Во время прочтения статьи, задался вопросом- а чем же собственно сложна проблема именования? В лекции Мохаммада Хаммуда об этом говорится довольно подробно. Плоское именование, структурированное, основанное на атрибутах и всё такое прочее..





пятница, 6 июля 2018 г.

Каузальная согласованность на сайте MariaDB

MariaDB - это ветка MySQL. 

У них на сайте нашел неплохую статью про каузальную согласованность (causal consistency). 

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

Когда транзакция выполняет сначала операцию чтения R, а затем операцию записи W (даже на разных объектах), эти операции оказываются связаны (т.к. значение, записанное W, м.б. создано на основе прочитанного R). Также будут связаны операция чтения и записи, если чтение произошло после записи  на том же объекте.

Кроме того, две записи, выполненные одним узлом, будут связаны. Ведь записав значение v в объект x узел будет знать, что чтение x даст v, поэтому более поздняя запись будет (потенциально) зависеть от более раннего.
  
Каузальная согласованность может быть достигнута за счет использования векторных часов или векторов версий.

Векторные часы описываются так. Каждый узел хранит вектор длины N , где N - число узлов.
Элемент с номером i содержит число, равное количеству сообщений, принятых с i-го хоста (хмм, по-моему, это расходится с классическим определением). Использование часов позволяет упорядочивать сообщения или откладывать прием сообщений.

Векторы версий. Нам нужно следить за обновлением M объектов, поэтому каждый узел хранит вектор длины M. Элемент с номером i - это количество записей в i-й объект. Когда какой-то узел обновляет   i-й объект, он увеличивает соотв элемент вектора, затем рассылает вектор и новое значение объекта всем остальным узлам. При приеме такого сообщения хост откладывает его доставку до тех пор, пока все элементы его вектора не станут больше или равны принятого вектора. Только после этого обновление применяется к объекту. Накладные расходы составляют O(M) и не зависят от количества узлов. 

В качестве приложений рассматриваются MMORPG и Facebook - но это как-нибудь потом. 

Гай о согласованности

Еще одна статья о согласованности в конечном счете - в блоге Гая Харрисона (кто это - мне неведомо).

Здесь интересно то, что сausal consistency, read your own writes, monotonic consistency рассматриваются как дополнительные опции, которые может предложить согласованность в конечном счете.

Много сказано об обозначении NRW (N копий данных, при чтении читаем с R реплик, при записи необходимо чтоб записалось как минимум на W реплик). 

Соотношение N=W означает, что пишем сразу на все реплики - это подход традиционных СУБД. Если делаем W=1 - получаем высокую производительность при записи. В этом случае стоит поставить R=N - тогда при чтении мы сможем понять, какая из копий данных верная (наиболее свежая).

В NoSQL обычно делают N>W>1. Т.е. должна произойти запись более чем на одну реплику, но не обязательно сразу писать на все. Поышение уровня согласованности в три этапа:
1. при R=1 получим, что БД считаем верной первую считанную копию данных;
2. при R>1 происходит чтение более одной копии, их можно сравнить и взять самую свежую;
3. при R+W>N у нас есть гарантия, что мы считаем хотя бы одну самую свежую копию данных (quorum assembly).  


Модели согласованности на ML Wiki

Перескажу на русском запись о консистентности в БД.

Согласованность (консистентность) в БД - это соблюдение всех ограничений (constraints). Например, в столбце Зарплата не м.б. записей в формате Дата.

Пример с банковскими счетами. Мы храним данные о счетах и общей сумме на всех счетах, обозначим ее T (от TOTAL). В любой момент времени сумма денег на всех счетах должна быть равна T. Но - в результате наших действий может возникнуть несогласованность. Мы кладем деньги на первый счет (скажем, 100 рублей). Далее обновится и T, но между обновлением первого счета и T данные будут несогласованы.

Здесь возникает понятие транзакции. Это набор действий, переводящих данные из одного согласованного состояние в другое (буква С в ACID). Но в процессе выполнения транзакции данные могут (имеют право) быть несогласованы. Соответственно, нам необходимо обновление счета и обновление T объединить в транзакцию.

Но что если в процессе транзакции произойдет сбой? Данные могут остаться в несогласованном состоянии. Избежать этого позволяют транзакционные логи СУБД, о которых тоже есть статья на ML Wiki.

В распределенных БД с согласованностью сложнее. Модели согласованности определяют правила видимости (visibility) и порядка обновлений (order of updates). 

Строгая согласованность. Все реплики видят обновления в одинаковом порядке. Любая операция чтения выдает самые свежие данные, в независимости от того, с какой реплики идет чтение. Необходим некий механизм распространения фиксаций (ommit propagation), например, двухфазная фиксация. Согласно CAP теореме невозможно достичь строгой согласованности одновременно с устойчивостью к разделению сети (partition-tolerance).

Согласованность в конечном счете (eventual consistency). Важен порядок получения обновлений. При  t→∞ все читатели увидят записи. Но обновления не атомарны, как в 
строгой согласованности.

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

HyperDex побил Mongo?

Нашел блог некоего Emin Gün Sirer. Человек занимается разработкой всякого софта (в т.ч. относящегося к биткоину), да ещё и  профессор в Корнуолльском университете.

Так вот, у него есть пост под названием On the Futility of Custom Consistency Models. Futility, кстати, переводится как тщетность. В посте Эмин пнул ученых, которые выдумывают разные модели согласованности и пишут про БигДату, приводя примеры структур данных длиной в байт.

Досталось и Монге. Она, оказывается, теряет данные. Из-за того, что жертвует согласованностью в угоду производительности. А вот детище Эмина HyperDex предлагает строгую согласованность (сериализуемые ACID транзакции) при скорости втрое выше, чем Монга. 

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