Я делаю проект, связанный со структурированной базой данных документов. У меня есть дерево категорий (~ 1000 категорий, до ~ 50 категорий на каждом уровне), каждая категория содержит несколько тысяч (скажем, до ~ 10000) структурированных документов. Каждый документ - это несколько килобайт данных в некоторой структурированной форме (я бы предпочел YAML, но это также может быть JSON или XML).
Пользователи этой системы выполняют несколько типов операций:
- получение этих документов по ID
- поиск документов по некоторым из структурированных атрибутов внутри них
- редактирование документов (т.е. добавление / удаление / переименование / объединение); каждая операция редактирования должна быть записана как транзакция с некоторым комментарием
- просмотр истории записанных изменений для конкретного документа (включая просмотр того, кто, когда и почему изменил документ, получение более ранней версии - и, возможно, возврат к этой, если потребуется)
Конечно, традиционным решением для этой проблемы было бы использование какой-то базы данных документов (например, CouchDB или Mongo), однако эта вещь с контролем версий (история) соблазнила меня на дикая идея - почему бы мне не использовать git
репозиторий в качестве серверная часть базы данных для этого приложения?
На первый взгляд, это можно решить так:
- категория = каталог, документ = файл
- получение документа по ID => смена директорий + чтение файла в рабочей копии
- редактирование документов с редактированием комментариев => совершение коммитов разными пользователями + сохранение сообщений коммитов
- history => обычный журнал git и получение старых транзакций
- search => это немного сложнее, я думаю, это потребует периодического экспорта категории в реляционную базу данных с индексацией столбцов, которые мы позволим искать по
Есть ли другие распространенные ошибки в этом решении? Кто-нибудь уже пробовал реализовать такой бэкэнд (т.е. для любых популярных фреймворков - RoR, node.js, Django, CakePHP)? Имеет ли это решение какие-либо возможные последствия для производительности или надежности - то есть доказано, что git будет намного медленнее, чем традиционные решения для баз данных, или будут какие-либо подводные камни масштабируемости / надежности? Я предполагаю, что кластер таких серверов, которые толкают / извлекают репозиторий друг друга, должен быть достаточно устойчивым и надежным.
В принципе, скажите мне, будет ли это решение работать и почему оно будет работать или нет?
Ответы:
Ответить на мой собственный вопрос - не лучший выход, но, поскольку я в конечном итоге отказался от этой идеи, я хотел бы поделиться логическим обоснованием, которое сработало в моем случае. Я хотел бы подчеркнуть, что это обоснование не может применяться ко всем случаям, поэтому решение остается за архитектором.
Как правило, первый главный момент, который упускается из виду, заключается в том, что я имею дело с многопользовательской системой, которая работает параллельно, одновременно с использованием моего сервера с тонким клиентом (т.е. просто веб-браузером). Таким образом, я должен поддерживать состояние для всех. Есть несколько подходов к этому, но все они либо слишком требовательны к ресурсам, либо слишком сложны для реализации (и, таким образом, в некотором роде убивают первоначальную цель выгрузки всей сложной реализации на git):
«Тупой» подход: 1 пользователь = 1 состояние = 1 полная рабочая копия репозитория, который сервер поддерживает для пользователя. Даже если мы говорим о довольно небольшой базе данных документов (например, 100 МБ) с ~ 100 тыс. Пользователей, поддержание полного клона репозитория для всех из них делает использование диска чрезмерным (т.е. 100 тыс. Пользователей умножить на 100 МБ ~ 10 ТиБ) , Что еще хуже, клонирование репозитория 100 MiB каждый раз занимает несколько секунд, даже если оно выполняется достаточно эффективно (то есть без использования git и распаковки-переупаковки), что неприемлемо, IMO. И что еще хуже - каждое редактирование, которое мы применяем к основному дереву, должно быть перенесено в репозиторий каждого пользователя, что (1) потребляет ресурсы, (2) может привести к неразрешенным конфликтам редактирования в общем случае.
По сути, это может быть так же плохо, как O (количество правок × данные × количество пользователей) с точки зрения использования диска, и такое использование диска автоматически означает довольно высокую загрузку ЦП.
Подход «Только активные пользователи»: поддерживать рабочую копию только для активных пользователей. Таким образом, вы обычно храните не полный репо-клон для каждого пользователя, а:
Таким образом, использование диска в этом случае достигает пика на O (количество правок × данные × количество активных пользователей), что обычно в ~ 100..1000 раз меньше, чем общее количество пользователей, но это делает вход / выход более сложным и медленным. , поскольку он включает в себя клонирование ветки для каждого пользователя при каждом входе в систему и извлечение этих изменений обратно при выходе из системы или истечении срока действия сеанса (что должно выполняться транзакционно => добавляет еще один уровень сложности). В абсолютных цифрах он снижает использование диска с 10 ТиБ до 10..100 ГиБ в моем случае, что может быть приемлемо, но, опять же, сейчас мы говорим о довольно небольшой базе данных в 100 МиБ.
Подход «разреженной проверки»: создание «разреженной проверки» вместо полномасштабного клона репо для каждого активного пользователя не очень помогает. Это может примерно в 10 раз сэкономить дисковое пространство, но за счет гораздо большей нагрузки на ЦП / диск при выполнении операций, связанных с историей, что убивает цель.
Подход «пула рабочих»: вместо того, чтобы каждый раз делать полноценных клонов для активного человека, мы могли бы держать пул «рабочих» клонов, готовый к использованию. Таким образом, каждый раз, когда пользователь входит в систему, он занимает одного «воркера», вытаскивая туда свою ветку из основного репозитория, и, когда он выходит из системы, он освобождает «воркера», который делает умный git hard reset, чтобы снова стать просто основной клон репо, готовый для использования другим пользователем, входящим в систему. Не очень помогает с использованием диска (он все еще довольно высок - только полный клон на активного пользователя), но, по крайней мере, он ускоряет вход / выход за счет еще больше сложности.
Тем не менее, обратите внимание, что я намеренно рассчитал количество довольно небольшой базы данных и базы пользователей: 100 000 пользователей, 1 000 активных пользователей, общая база данных 100 MiB + история изменений, 10 MiB рабочей копии. Если вы посмотрите на более известные краудсорсинговые проекты, там гораздо больше цифр:
Очевидно, что для такого количества данных / активности такой подход был бы совершенно неприемлем.
Как правило, это сработало бы, если бы можно было использовать веб-браузер в качестве «толстого» клиента, то есть выполнять операции git и сохранять почти полную проверку на стороне клиента, а не на стороне сервера.
Есть и другие моменты, которые я упустил, но они не так уж плохи по сравнению с первым:
Таким образом, нижняя строка : это является возможным, но для большинства современных usecases не будет в любом месте вблизи оптимального решения. Лучшей альтернативой, вероятно, будет сворачивание вашей собственной реализации документа-редактирования-истории-в-SQL или попытка использовать любую существующую базу данных документов.
источник
Действительно интересный подход. Я бы сказал, что если вам нужно хранить данные, используйте базу данных, а не репозиторий исходного кода, который предназначен для очень конкретной задачи. Если бы вы могли использовать Git из коробки, то все в порядке, но вам, вероятно, потребуется построить над ним слой репозитория документов. Значит, вы могли бы построить его и на традиционной базе данных, верно? И если вас интересует встроенный контроль версий, почему бы просто не использовать один из инструментов репозитория документов с открытым исходным кодом ? Есть из чего выбирать.
Что ж, если вы все равно решите использовать бэкэнд Git, то в основном он будет работать в соответствии с вашими требованиями, если вы реализуете его, как описано. Но:
1) Вы упомянули «кластер серверов, которые толкают / подтягивают друг друга» - я думал об этом некоторое время, но все еще не уверен. Вы не можете нажать / вытащить несколько репозиториев как атомарную операцию. Интересно, могла ли быть возможность некоторого беспорядка слияния во время одновременной работы.
2) Возможно, вам это не нужно, но очевидная функциональность репозитория документов, который вы не указали, - это контроль доступа. Вы можете ограничить доступ к некоторым путям (= категориям) через подмодули, но, вероятно, вы не сможете легко предоставить доступ на уровне документа.
источник
мои 2 пенса стоят. Немного тоскует, но ... У меня было подобное требование в одном из моих инкубационных проектов. Как и ваши, мои ключевые требования, когда база данных документов (xml в моем случае) с управлением версиями документов. Это было для многопользовательской системы с множеством вариантов использования для совместной работы. Я предпочел использовать доступные решения с открытым исходным кодом, которые поддерживают большинство ключевых требований.
Вкратце: я не смог найти ни одного продукта, который обеспечивал бы и то, и другое, достаточно масштабируемым (количество пользователей, объемы использования, хранилище и вычислительные ресурсы). Я был склонен к git из-за всех многообещающих возможностей, и (вероятные) решения, которые можно было бы найти из этого. По мере того, как я больше играл с опцией git, переход от перспективы одного пользователя к перспективе нескольких (милли) пользователей стал очевидной проблемой. К сожалению, мне не удалось провести серьезный анализ производительности, как это сделали вы. (.. ленив / рано бросить .... для версии 2, мантра) Power to you !. Как бы то ни было, моя предвзятая идея с тех пор трансформировалась в следующую (все еще предвзятую) альтернативу: набор инструментов, которые являются лучшими в своих отдельных сферах, базах данных и контроле версий.
Пока работа еще продолжается (... и немного игнорируется), преобразованная версия просто такая.
По сути, это будет означать добавление в базу данных подключаемого модуля управления версиями с неким интеграционным клеем, который вам, возможно, придется разработать, но это может быть намного проще.
Как это будет (должно) работать, так это то, что основной обмен данными многопользовательского интерфейса осуществляется через базу данных. СУБД будет обрабатывать все забавные и сложные проблемы, такие как многопользовательский, параллелизм, атомарные операции и т. Д. На бэкэнде VCS будет выполнять контроль версий для одного набора объектов данных (без параллелизма или многопользовательских проблем). Для каждой действующей транзакции в базе данных контроль версий осуществляется только для тех записей данных, которые должны были эффективно измениться.
Что касается связующего клея, то он будет в форме простой функции взаимодействия между базой данных и VCS. С точки зрения дизайна, в качестве простого подхода будет интерфейс, управляемый событиями, с обновлением данных из базы данных, запускающим процедуры контроля версий (подсказка: предполагая , что Mysql, использование триггеров и sys_exec () бла-бла ...). С точки зрения сложности реализации, он будет варьироваться от простого и эффективного (например, создание сценариев) до сложного и замечательного (некоторый программный интерфейс коннектора). Все зависит от того, насколько сумасшедшим вы хотите пойти с этим, и сколько пота капитала вы готовы потратить. Я считаю, что волшебство должно творить простые сценарии. А для доступа к конечному результату, различным версиям данных, простой альтернативой является заполнение клона базы данных (скорее, клона структуры базы данных) данными, на которые ссылается тег версии / id / hash в VCS. опять же, этот бит будет простым запросом / переводом / отображением интерфейса.
Есть еще несколько проблем и неизвестных моментов, которые необходимо решить, но я полагаю, что влияние и актуальность большинства из них будут во многом зависеть от требований вашего приложения и вариантов использования. Некоторые могут просто перестать быть проблемами. Некоторые из проблем включают соответствие производительности между двумя ключевыми модулями, базой данных и VCS, для приложения с высокой частотой обновления данных, масштабированием ресурсов (хранилище и вычислительная мощность) с течением времени на стороне git в качестве данных и пользователей. рост: устойчивый, экспоненциальный или в конечном итоге плато
Из приведенного выше коктейля вот то, что я сейчас варию
Некоторые забавные факты - git на самом деле очищает вещи для оптимизации хранения, такие как сжатие и хранение только дельт между ревизиями объектов - ДА, git хранит только наборы изменений или дельты между ревизиями объектов данных, где это применимо (он знает когда и как) . Ссылка: packfiles, глубоко внутри Git - Обзор хранилища объектов git (файловая система с адресацией по содержимому), показывает поразительное сходство (с точки зрения концепции) с базами данных noSQL, такими как mongoDB. Опять же, за счет пота капитала, он может предоставить более интересные возможности для интеграции 2 и настройки производительности.
Если вы зашли так далеко, позвольте мне, если вышеизложенное может быть применимо к вашему случаю, и предполагая, что это так, как это будет соответствовать некоторым аспектам вашего последнего всеобъемлющего анализа производительности.
источник
Я реализовал библиотеку Ruby поверх
libgit2
нее, что упрощает реализацию и исследование. Есть некоторые очевидные ограничения, но это также довольно освобождающая система, поскольку вы получаете полную цепочку инструментов git.Документация включает в себя некоторые идеи о производительности, компромиссах и т. Д.
источник
Как вы упомянули, с многопользовательским режимом справиться немного сложнее. Одним из возможных решений было бы использование файлов индекса Git для конкретного пользователя, что привело бы к
Уловка состоит в том, чтобы объединить
GIT_INDEX_FILE
переменную окружения Git с инструментами для создания коммитов Git вручную:Схема решения следует (фактические хэши SHA1 опущены в командах):
В зависимости от ваших данных вы можете использовать задание cron для слияния новых ссылок,
master
но разрешение конфликтов, пожалуй, самая сложная часть здесь.Приветствуются идеи по упрощению.
источник