Skip to content

Blackdeer1524/GraphDB

Repository files navigation

GraphDB

В корне проекта находится .env.example. Вы можете его отредактировать по своему усмотрению и переименовать его в .env для запуска приложения.

Важно: в корне проекта всегда должен находиться файл .env, иначе проект не запустится.

Для запуска выполните команду

make run

Для сборки исполняемого файла выполните команду

make build

Принцип работы

Этот проект - реализация распределенной графовой СУБД. Поддерживает операции на модификацию и на чтение, причем операции на модификацию отправляются исключительно лидеру кластера, а на чтение - любому узлу в кластере.

Достижение консенсуса

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

Выполнение DML-операций

Сейчас СУБД позволяет отправлять простейшие запросы извне, например создание/получение узла. Пример таких запросов (cURL):

Создание вершины

curl --request POST \
  --url http://localhost:8080/raft/vertices \
  --header 'content-type: application/json' \
  --data '{
  "table": "main",
  "record": {
    "properties": {
      "money": 100
    }
  }
}'

Получение вершины

curl --request GET \
  --url 'http://localhost:8080/raft/vertices?id=1ed622f0-31e7-4bb0-ad35-a4e6bef2bf9e&table=main'

Потенциал для доработки

Управление таблицами

Сейчас не реализованы операции добавления/удаления таблиц и схем (DDL-операции). При запуске создается таблица main для узлов и схема данных money (src/raft/node.go). Эти операции необходимо реализовать аналогично DML-операциям.

Конфигурация без обязательного файла .env

Сейчас наличие файла .env в корне проекта обязательно. Это поведение можно поменять в src/app/env.go.

Запуск на нескольких машинах

Текущая реализация - демо-вариант, который позволяет быстро запустить несколько узлов на одной машине. При необходимости логику запуска можно поменять в src/app/server.go. В данный момент при запуске мы опираемся на количество адресов в .env, и по количеству адресов мы запускаем соответствующее число узлов.

Внедрение шардирования

Внедрение шардирования для графовой БД - тяжелый процесс, и потребует большого числа доработок. Во первых потребуется некий оркестратор, который будет определять, на какой узел мы должны отправить запрос по содержимому самого запроса. Сейчас уже имеется оркестрация запросов к лидер-узлу для операций модификации в src/delivery/server.go, однако реализация оркестрации по содержимому будет выглядеть сложнее: потребуется определиться, будет ли атрибут, по которому мы шардируемся, динамическим, или же это будет ID вершины/ребра. Возникает так же вопрос: как мы должны хранить ребро между узлами на разных шардах, к какому шарду будет относиться это ребро?

Транзакции

Запросы

Работа с данными реализована в директории ./src/query/. На текущий момент реаллизованы

  • ddl.go
    • Создание/удаление типов вершин и ребер
  • dml.go
    • получение ребер и вершин по их служебному идентификатору;
    • вставка ребер и вершин
    • обновление вершин
  • sow.go
    • обход вершин на заданной глубине с фильтрацией по вершинам (GetVerticesOnDepth)
    • получение всех вершин с заданным значением поля (скан по типу вершины) (GetAllVertexesWithFieldValue)
    • получение всех вершин с заданным значением поля с фильтрацией по ребрам и учетом степени вершин (скан по типу вершины) (GetAllVertexesWithFieldValue2)
    • подсчет треугольников в неориентированном графе (GetAllTriangles)
    • [!БЕЗ ТЕСТОВ!] Сумма значений полей соседей каждой вершины (SumNeighborAttributes)

Как запускать транзакции

За выполнением запросов отвечает структура Executor. Пример сетапа структуры описан в файле executor_test.go. Пример её использования можно также найти в этом файле.

Запуск транзакции выполняется функцией execute, описанный в src/raft/node.go. Пример использования метода можно найти в executor_test.go. В этом файле используется копия метода с тем же названием.

Полноценные примеры запуска транзакций приведены в том же executor_test.go.

Дополнительно

Существует ветка experimental, в которой несколько переделана логика взятия блокировок, из-за чего существенно повышается производительность. Это связано с тем, что там убраны блокировки-намерения на базу данных, вместо которых там стандартные S и X блокировки на каталог. В ветке также прописаны дополнительные успешно работающие тесты, но в полной корректности работы до конца не уверен. В ветке также дополнительно реализованы пару DML методов для вершин и ребер.

Для улучшения параллелизма в БД нужно как-то перепроектировать взятие блокировок в BufferPool'е, DiskManager'е и WAL, так как очень много блокировок. Нужны кастомные структуры данных, а не дефолтные гошные. Но для исправления нужно прямо-таки очень много работы, так как на последовательное взятие блокировок пронесено по всей системе.

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

About

OLTP Graph DBMS

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •