53 Commits

Author SHA1 Message Date
f092723a1a Upload files to "internal/repl" 2026-07-08 21:48:11 +00:00
8b6f2e2c0c Delete internal/repl/repl.go 2026-07-08 21:47:55 +00:00
55bb0e7cc0 Update README.md 2026-07-08 21:40:42 +00:00
f494fca375 Update README.md 2026-07-08 21:38:16 +00:00
6cde3c4cc9 Update README.md 2026-07-08 21:31:39 +00:00
5447aa45d1 Update README.md 2026-07-08 21:30:58 +00:00
2da91c8bc1 Update README.md 2026-07-08 20:51:13 +00:00
cbaf5a4918 Upload files to "internal/storage" 2026-07-08 20:46:51 +00:00
29e66d01fb Upload files to "internal/repl" 2026-07-08 20:46:14 +00:00
564d0ac688 Delete internal/repl/repl.go 2026-07-08 20:45:55 +00:00
46c73814f6 Upload files to "internal/storage" 2026-07-08 20:45:10 +00:00
0f2117d8a1 Upload files to "internal/storage" 2026-07-08 20:44:57 +00:00
e7ab44041c Delete internal/storage/transaction.go 2026-07-08 20:44:26 +00:00
45dd4ccdb8 Delete internal/storage/collection.go 2026-07-08 20:44:17 +00:00
75506b9fb7 Delete internal/storage/persistence.go 2026-07-08 20:44:07 +00:00
2de05922c5 Update README.md 2026-07-08 20:42:45 +00:00
e6d064b6cf Update README.md 2026-07-05 21:22:12 +00:00
d1a57ee199 Update README.md 2026-07-05 21:21:11 +00:00
08dbde5731 Update README.md 2026-06-25 20:58:59 +00:00
a75f29a231 Delete internal/backup/111backup_scheduler.go 2026-06-25 20:49:51 +00:00
c858b1eec3 Upload files to "internal/backup" 2026-06-25 20:49:44 +00:00
2cc2249625 Update internal/backup/111backup_scheduler.go 2026-06-25 20:49:26 +00:00
0a6cfe8f0e Upload files to "internal/storage" 2026-06-25 20:48:50 +00:00
4593c30076 Delete internal/storage/transaction.go 2026-06-25 20:48:28 +00:00
9150dbab1f Update README.md 2026-06-22 20:35:19 +00:00
8d26429021 Update README.md 2026-06-21 20:12:18 +00:00
ab9e8375cb Update README.md 2026-06-21 14:20:59 +00:00
234a8c23c5 Update README.md 2026-06-21 14:20:09 +00:00
a037cc4bb8 Update README.md 2026-06-21 13:54:38 +00:00
c235c959e6 Update README.md 2026-06-21 13:54:05 +00:00
5201fc4055 Update README.md 2026-06-21 13:53:12 +00:00
77d12a6f8c Upload files to "internal/api" 2026-06-21 13:28:25 +00:00
592becc486 Delete internal/api/webui.go 2026-06-21 13:28:03 +00:00
96b20b7d58 Upload files to "internal/storage" 2026-06-20 17:44:43 +00:00
3ca246432d Delete internal/storage/transaction.go 2026-06-20 17:44:31 +00:00
29a1f8dc27 Delete internal/storage/11document.go 2026-06-20 17:43:59 +00:00
d49729bf1a Upload files to "internal/storage" 2026-06-20 17:43:40 +00:00
12dbd16f7b Update internal/storage/11document.go 2026-06-20 17:43:20 +00:00
8fa28ada45 Upload files to "internal/commands" 2026-06-20 17:42:31 +00:00
881bdbc5dc Delete internal/commands/crud.go 2026-06-20 17:42:09 +00:00
f63ae0a523 Update README.md 2026-06-20 16:29:07 +00:00
50d3b72d0b Update README.md 2026-06-20 16:25:58 +00:00
aa306c4159 Add ISSUE_TEMPLATE/question.yaml 2026-06-19 20:11:47 +00:00
9214729d2f Add ISSUE_TEMPLATE/feature_request.yaml 2026-06-19 20:11:09 +00:00
5c7100a67c Add ISSUE_TEMPLATE/bug_report.yaml 2026-06-19 19:21:40 +00:00
a002d6038b Update README.md 2026-06-18 19:53:36 +00:00
2fd82f2939 Update internal/storage/persistence.go 2026-06-18 19:48:08 +00:00
48fe3447ad Upload files to "internal/storage" 2026-06-18 19:38:31 +00:00
f170024e75 Delete internal/storage/persistence.go 2026-06-18 19:38:06 +00:00
38a229a107 Delete internal/backup/11backup_scheduler.go 2026-06-18 19:37:48 +00:00
35372dc06a Upload files to "internal/backup" 2026-06-18 19:37:35 +00:00
525f9d6d82 Update internal/backup/11backup_scheduler.go 2026-06-18 19:37:08 +00:00
7bebd91ab6 Update README.md 2026-06-17 21:14:38 +00:00
11 changed files with 5237 additions and 3617 deletions

View File

@@ -0,0 +1,59 @@
name: "🐛 Сообщить об ошибке"
description: "Создайте отчёт, чтобы помочь нам исправить проблему"
title: "[BUG]: "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
## Спасибо, что помогаете сделать Futriix лучше!
Пожалуйста, опишите проблему максимально подробно.
- type: textarea
id: description
attributes:
label: "Описание ошибки"
description: "Чётко и ясно опишите, в чём заключается проблема."
placeholder: "Например: При попытке сохранить документ с полем типа 'timestamp' возникает паника..."
validations:
required: true
- type: textarea
id: steps
attributes:
label: "Шаги для воспроизведения"
description: "Опишите пошагово, что нужно сделать, чтобы увидеть ошибку."
placeholder: |
1. Запустить СУБД с конфигом...
2. Отправить запрос...
3. Увидеть ошибку...
validations:
required: true
- type: input
id: version
attributes:
label: "Версия Futriix"
description: "Какую версию вы используете? (Например, 2.0 i²)"
placeholder: "v2.0"
validations:
required: true
- type: dropdown
id: os
attributes:
label: "Операционная система"
options:
- Linux
- Windows
- macOS
- Другая
validations:
required: true
- type: textarea
id: logs
attributes:
label: "Логи или вывод терминала"
description: "Вставьте сюда любые сообщения об ошибках или логи (можно в виде текста)."
render: shell

View File

@@ -0,0 +1,36 @@
name: "🚀 Предложить новую функцию"
description: "Поделитесь идеей, которая улучшит Futriix"
title: "[FEATURE]: "
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
## Мы открыты к вашим идеям!
Расскажите, какую возможность вы хотели бы видеть.
- type: textarea
id: idea
attributes:
label: "Ваша идея"
description: "Опишите, что бы вы хотели добавить или изменить."
placeholder: "Было бы здорово реализовать поддержку индексов для поля 'name'..."
validations:
required: true
- type: textarea
id: benefit
attributes:
label: "Какую проблему это решает?"
description: "Объясните, зачем это нужно вам и другим пользователям."
placeholder: "Это ускорит поиск по документам в 3 раза..."
- type: textarea
id: lua_example
attributes:
label: "Пример использования (если связано с Lua-плагином)"
description: "Если ваша идея касается системы плагинов, приведите пример кода на Lua."
render: lua
placeholder: |
-- Например, как бы вы хотели использовать новый движок?
local my_engine = futriix.new_engine("custom")

View File

@@ -0,0 +1,27 @@
name: "❓ Задать вопрос"
description: "Нужна помощь или совет по использованию Futriix"
title: "[QUESTION]: "
labels: ["question"]
body:
- type: markdown
attributes:
value: |
## Мы здесь, чтобы помочь!
Не стесняйтесь задавать любые вопросы по установке, настройке или использованию СУБД.
- type: textarea
id: question
attributes:
label: "Ваш вопрос"
description: "Чётко сформулируйте, что именно вас интересует."
placeholder: "Как правильно настроить кластер из двух узлов?"
validations:
required: true
- type: textarea
id: context
attributes:
label: "Дополнительный контекст"
description: "Расскажите, что вы уже попробовали, или приложите фрагмент кода/конфига."
placeholder: "Мой конфиг выглядит так: ..."
render: yaml

110
README.md
View File

@@ -54,7 +54,7 @@
<li><a href="#триггеры">Триггеры</a></li> <li><a href="#триггеры">Триггеры</a></li>
<li><a href="#сжатие-данных">Сжатие данных</a></li> <li><a href="#сжатие-данных">Сжатие данных</a></li>
<li><a href="#графический-интерфейс">Графический интерфейс</a></li> <li><a href="#графический-интерфейс">Графический интерфейс</a></li>
<li><a href="#дорожная-карта">Дорожная карта</a></li> <li><a href="#план-развития">План развития</a></li>
<li><a href="#контакты">Контакты</a></li> <li><a href="#контакты">Контакты</a></li>
</ol> </ol>
<!-- </details> --> <!-- </details> -->
@@ -63,12 +63,13 @@
## О проекте ## О проекте
> [!CAUTION] > [!CAUTION]
> **ALPHA VERSION**<br><br>**Проект стабилен в тестовых сценариях, но категорически не рекомендуется для промышленного использования до выхода версии 3.0. Мы открыты к обратной связи и тестированию!** > **ALPHA VERSION**<br><br>**Проект достаточно стабилен в тестовых сценариях, но категорически не рекомендуется для промышленного использования до выхода версии 3.0. Мы открыты для предложений, и рады обратной связи!**
futriix - это легковесная, распределённая NOSQL, использующая алгоритмы неблокирующей синхронизации - `wait-free` и `lock-free` in-memory СУБД, реализованная на языке Go с поддержкой плагинов на языке lua использующая алгоритм консенсуса Raft. <br> futriix - это легковесная, распределённая NOSQL, использующая алгоритмы неблокирующей синхронизации - `wait-free` и `lock-free` in-memory СУБД, реализованная на языке Go с поддержкой плагинов на языке lua использующая алгоритм консенсуса Raft. <br>
По своей сути, Futriis является лёгкой HTAP-СУБД с уклоном в OLTP благодаря wait-free структурам и ACID-транзакциям, а также мощными OLAP-возможностями через индексы, триггеры, Lua-плагины и аналитические функции. Это позволяет обрабатывать и анализировать данные в режиме, близком к реальному времени, в первую очередь для эксплуатации в замкнутых программных средах под управлением ОС на базе ядра Illumos и Solaris (OpenIndiana Hipster, Oracle Solaris). Архитектурное решение использовать отдельные индексы от данных, атомарные операции и версионирование позволяет эффективно обрабатывать смешанную нагрузку без необходимости применять отдельные системы для OLTP и OLAP.<br> По своей сути, Futriis является лёгкой HTAP-СУБД с уклоном в OLTP благодаря wait-free структурам и ACID-транзакциям, а также мощными OLAP-возможностями через индексы, триггеры, Lua-плагины и аналитические функции. Это позволяет обрабатывать и анализировать данные в режиме, близком к реальному времени, в первую очередь для эксплуатации в замкнутых программных средах под управлением ОС на базе ядра Illumos и Solaris (OpenIndiana Hipster, Oracle Solaris). <br>
Архитектурное решение использовать отдельные индексы от данных, атомарные операции и версионирование позволяет эффективно обрабатывать смешанную нагрузку без необходимости применять отдельные системы для OLTP и OLAP.<br>
В futriix реализован WUI-интерфейс для удобства её администрирования и эксплуатации. В futriix реализован WUI-интерфейс для удобства её администрирования и эксплуатации.
Но она также совместима с популярными Linux-дистрибутивами (Debian,Ubuntu,Fedora), т.е. операционными системами построенными на базе ядра Linux. Кроме того она совместима с популярными Linux-дистрибутивами (Debian,Ubuntu,Fedora).
<p align="right">(<a href="#readme-top">К началу</a>)</p> <p align="right">(<a href="#readme-top">К началу</a>)</p>
@@ -85,14 +86,16 @@ futriix - это легковесная, распределённая NOSQL, и
* **База Данных(БД)** - это структурированное, организованное хранилище данных, которое позволяет удобно собирать, хранить, управлять и извлекать информацию. * **База Данных(БД)** - это структурированное, организованное хранилище данных, которое позволяет удобно собирать, хранить, управлять и извлекать информацию.
* **Система Управления Базами Данных(СУБД)** - это программное обеспечение, которое позволяет создавать, управлять и взаимодействовать с базами данных * **Система Управления Базами Данных(СУБД)** - это программное обеспечение, которое позволяет создавать, управлять и взаимодействовать с базами данных
* **Таппл (Tapple)** - аналог базы данных в РСУБД * **Слайс (Slice-в пер.с англ.слой)**- в терминах субд Futriix имеет два значения:
* **Слайс (Slice)** - аналог таблицы * **1.** Cиноним "база данных"
* **Кортеж (Tuple)** - аналог записи в таблице * **2.** Термин пришедший из терминологии суд MongoDB, а именно: Логический и физически изолированный фрагмент коллекции документов, полученный в результате горизонтального партиционирования (шардирования) и размещенный на определенном узле кластера с целью масштабирования производительности и объема данных.
* **Коллекция (Collection)** - аналог таблицы
* **Поле (Field)** - аттрибут документов
* **Кортеж (Tuple)** - вложенный документ в субд Futriix
* **Мультимодельная СУБД** - это СУБД, которая объединяет в себе поддержку нескольких моделей данных (реляционной, документной, графовой, ключ-значение и др.) в рамках единого интегрированного ядра. * **Мультимодельная СУБД** - это СУБД, которая объединяет в себе поддержку нескольких моделей данных (реляционной, документной, графовой, ключ-значение и др.) в рамках единого интегрированного ядра.
* **Резидентная СУБД** - это СУБД, которая работает непрерывно в оперативной памяти (RAM). * **Резидентная СУБД** - это СУБД, которая работает непрерывно в оперативной памяти (RAM).
* **Инстанс** - это запущенный экземляр базы данных. * **Инстанс** - это запущенный экземляр базы данных.
* **Узел (хост,нода,шард)** - это отдельный сервер (физический или виртуальный), который является частью кластера или распределенной системы и выполняет часть общей работы. * **Узел (хост,нода,шард)** - это отдельный сервер (физический или виртуальный), который является частью кластера или распределенной системы и выполняет часть общей работы.
* **Слайс (от англ. "slice"-слой)** - это логический и физически изолированный фрагмент коллекции документов, полученный в результате горизонтального партиционирования (шардирования) и размещенный на определенном узле кластера с целью масштабирования производительности и объема данных.
* **Репликасет** - это группа серверов СУБД, объединенных в отказоустойчивую конфигурацию, где один узел выполняет роль первичного (принимающего операции записи), а один или несколько других - роль вторичных (синхронизирующих свои данные с первичным и обслуживающих чтение), с автоматическим переизбранием первичного узла в случае его сбоя. * **Репликасет** - это группа серверов СУБД, объединенных в отказоустойчивую конфигурацию, где один узел выполняет роль первичного (принимающего операции записи), а один или несколько других - роль вторичных (синхронизирующих свои данные с первичным и обслуживающих чтение), с автоматическим переизбранием первичного узла в случае его сбоя.
* **Временная метка (time stamp)** - это автоматически фиксируемое значение времени создания, изменения или удаления объекта в СУБД, представленное в формате Unix-миллисекунд (количество миллисекунд, прошедших с 1 января 1970 года) с возможностью отображения в человекочитаемом виде YYYY-MM-DD HH:MM:SS.mmm. Необходима для понимание последовательности операций при сбоях, выявления аномалий в поведении системы,архивация старых записей, отслеживание несанкционированных изменений, автоматический выход из сессий с ограниченным временем действия, Статистика активности за период) * **Временная метка (time stamp)** - это автоматически фиксируемое значение времени создания, изменения или удаления объекта в СУБД, представленное в формате Unix-миллисекунд (количество миллисекунд, прошедших с 1 января 1970 года) с возможностью отображения в человекочитаемом виде YYYY-MM-DD HH:MM:SS.mmm. Необходима для понимание последовательности операций при сбоях, выявления аномалий в поведении системы,архивация старых записей, отслеживание несанкционированных изменений, автоматический выход из сессий с ограниченным временем действия, Статистика активности за период)
* **OLTP (Online Transactional Processing-Онлайн обработка транзакций)**- это технология обработки транзакций в режиме реального времени. Её основная задача заключается в обеспечении быстрого и надёжного выполнения операций, которые происходят ежесекундно в бизнесе. Они обеспечивают быстрое выполнение операций вставки, обновления и удаления данных, поддерживая целостность и надежность транзакций. * **OLTP (Online Transactional Processing-Онлайн обработка транзакций)**- это технология обработки транзакций в режиме реального времени. Её основная задача заключается в обеспечении быстрого и надёжного выполнения операций, которые происходят ежесекундно в бизнесе. Они обеспечивают быстрое выполнение операций вставки, обновления и удаления данных, поддерживая целостность и надежность транзакций.
@@ -364,20 +367,27 @@ done
> СУБД futriiX полностью совместима по синтаксису запросов с NOSQL-субд MongoDB. > СУБД futriiX полностью совместима по синтаксису запросов с NOSQL-субд MongoDB.
> Вы можете использовать знакомые NoSQL-конструкции и драйверы, легко мигрируя с существующей инфраструктуры. > Вы можете использовать знакомые NoSQL-конструкции и драйверы, легко мигрируя с существующей инфраструктуры.
В субд futriix поддерживаются MongoDB-подобный синтаксис для команд, являющийся основными в любой субд из класса **CRUD (Create,Read, Update, Delete- Создание, Чтение, Обновление, Удаление**) работы с документами: db.collection.insert(), find(), update(), delete(). Операции выполняются wait-free с использованием атомарных sync.Map, поддерживают автоматическую генерацию _id и валидацию схемы. Кроме того, каждый объект субд будь то таппл или поле, содержат в себе автоматически создаваемую временную метку, обладающей следующими свойствами: Futriix поддерживает привычный MongoDBсинтаксис для работы с документами.
Вы можете использовать стандартные команды: insert(), find(), update(), delete() — точно так же, как в MongoDB.
Все CRUDоперации (создание, чтение, обновление, удаление) выполняются без блокировок (waitfree) и гарантируют корректную работу при параллельном доступе за счёт атомарных структур данных.
При этом система автоматически:
* Создаёт уникальный идентификатор _id для каждого документа;
* Проверяет соответствие схеме (валидация);
* Добавляет временную метку к каждому объекту (таблице или полю).
> [!NOTE]
>**Выполнение операций**<br>
> Операции выполняются в рамках гарантий изоляции, обеспечиваемых MVCC и протоколом консенсуса Raft.
> Для распределённых транзакций применяется протокол 2PC.
* Автоматические — не требуют ручного указания
* Атомарные — фиксируются на уровне каждой операции
* Высокоточные — до миллисекунды
* Неизменяемые — created_at никогда не меняется
* Аудируемые — все изменения протоколируются в audit log
```sh ```sh
# Создание новой базы данных # Создание новой базы данных
futriix:~> create database company futriix:~> create slice company
✓ Database 'company' created at 2026-01-15 10:30:45.123 ✓ Database 'company' created at 2026-01-15 10:30:45.123
futriix:~> create database shop futriix:~> create slice shop
✓ Database 'shop' created at 2026-01-15 10:30:46.456 ✓ Database 'shop' created at 2026-01-15 10:30:46.456
# Переключение на базу данных # Переключение на базу данных
@@ -624,6 +634,48 @@ futriix:~> db.startSession()
В субд **futriix** для обеспечения надёжности (durability) и быстрого восстановления бд из резевной копии, реализована полноценная поддержка WAL (Write-Ahead Logging). Журнал WAL по умолчанию хранится в файле **futriix.wal**, находящимся в каталоге **futriix**, а также поддержка ACID-транзакций с MVCC (Multi-Version Concurrency Control). В субд **futriix** для обеспечения надёжности (durability) и быстрого восстановления бд из резевной копии, реализована полноценная поддержка WAL (Write-Ahead Logging). Журнал WAL по умолчанию хранится в файле **futriix.wal**, находящимся в каталоге **futriix**, а также поддержка ACID-транзакций с MVCC (Multi-Version Concurrency Control).
Доступны команды startSession(), startTransaction(), commitTransaction(), abortTransaction() с восстановлением после сбоев через журнал предзаписи. Доступны команды startSession(), startTransaction(), commitTransaction(), abortTransaction() с восстановлением после сбоев через журнал предзаписи.
> [!IMPORTANT]
> **Матрица гарантий согласованности** <br>
> Ниже приведена матрица гарантий согласованности, призванная дать ответ на потенциальный возможный вопрос пользователя: "А вдруг у меня
> данные потеряются"?
# Матрица гарантий согласованности Futriix
| Операция | Уровень изоляции | Поведение при нормальной работе | Поведение при сетевых сбоях | Восстановление после сбоя |
|----------|------------------|--------------------------------|----------------------------|---------------------------|
| **Чтение (Read)** | **Read Committed** + MVCC | • Чтение всегда возвращает только закоммиченные данные<br>• MVCC предоставляет снапшот на момент начала чтения<br>• Используется Visibility Map для быстрого доступа к версиям<br>• Кеширование через ReadTimestampCache | • При потере соединения - операция повторяется автоматически (идиемпотентность)<br>• Если узел недоступен - запрос перенаправляется к реплике (Raft)<br>• Чтение из кэша возможно при недоступности основного узла | • После восстановления узла - чтение продолжается с момента прерывания<br>• WAL не требуется для чтения (только для записи)<br>• Снапшоты MVCC восстанавливаются из documentVersions |
| **Запись (Write)** | **Read Committed** | • Запись сначала сохраняется в WAL (атомарно)<br>• Затем применяется к in-memory структурам<br>• Индексы обновляются атомарно с документом<br>• Атомарное обновление метаданных коллекции | • Если WAL запись не подтверждена - операция не применяется<br>• При сбое до коммита - данные не теряются (WAL)<br>• При потере лидера (Raft) - запись перенаправляется к новому лидеру<br>• Используется fsync для гарантии записи на диск | • После восстановления - запись повторяется из WAL<br>• Автоматическое применение WAL при загрузке<br>• Консистентность через LSN (Log Sequence Number)<br>• Segmented WAL позволяет восстанавливать частичные записи |
| **Транзакция (BEGIN...COMMIT)** | **Read Committed / Repeatable Read** (MVCC) | • Транзакция атомарна: все или ничего<br>• MVCC предоставляет снапшот на момент начала транзакции<br>• Операции внутри транзакции изолированы<br>• Savepoints для частичного отката<br>• Deadlock detection с автоматическим abort-ом | • При сбое в середине транзакции - автоматический откат<br>• WAL гарантирует восстановление закоммиченных транзакций<br>• 2PC для распределённых транзакций с таймаутом (10 сек)<br>• Prepared транзакции автоматически откатываются при таймауте | • Асинхронное восстановление из WAL<br>• Восстановление только закоммиченных транзакций<br>• Pending 2PC транзакции проверяются на таймаут<br>• Recovery Manager обрабатывает записи параллельно |
| **Индексация** | **Read Committed** | • Индексы обновляются атомарно с документом<br>• Уникальные индексы проверяются перед вставкой<br>• Индексы хранятся в sync.Map (wait-free)<br>• Поддержка составных индексов | • Индексы восстанавливаются из данных при загрузке<br>• При сбое - индексы перестраиваются автоматически<br>• Консистентность через LSN<br>• Уникальные индексы проверяются при восстановлении | • Индексы перестраиваются из документов при старте<br>• WAL содержит операции обновления индексов<br>• Автоматическое восстановление целостности индексов<br>• Проверка дубликатов при восстановлении уникальных индексов |
| **Удаление (Delete)** | **Read Committed** | • Soft delete сохраняет данные (метка deleted_at)<br>• Удаление из индексов происходит атомарно<br>• Физическое удаление - только после подтверждения<br>• Атомарное обновление счётчиков | • При сбое - операция повторяется из WAL<br>• Soft delete защищает от потери данных<br>• Окончательное удаление - после подтверждения всеми репликами<br>• Permanent delete требует подтверждения | • Soft delete записи восстанавливаются из WAL<br>• Permanent delete повторяется из WAL<br>• Счётчики документов восстанавливаются атомарно |
| **Репликация (Raft)** | **Linearizable** (для записей) / **Read Committed** (для чтений) | • Записи проходят через Raft-журнал<br>• Линейная консистентность для записей<br>• Чтения могут быть из реплик (Read Committed)<br>• Автоматическое переизбрание лидера | • При сбое лидера - автоматический выбор нового (Raft)<br>• Запросы перенаправляются к новому лидеру<br>• Данные согласованы через журнал Raft<br>• Read-запросы могут обслуживаться репликами | • Raft журнал восстанавливается из WAL<br>• Новый лидер применяет все закоммиченные записи<br>• Реплики синхронизируются с лидером<br>• Автоматическое восстановление кластера |
| **Шардирование (Range Shards)** | **Read Committed** | • Диапазонные шарды с динамическим сплитом/мерджем<br>• Данные распределены по диапазонам ключей<br>• Предсказуемая нагрузка на узлы<br>• Возможность предварительного добавления узлов под горячие диапазоны | • При сбое узла - шард перераспределяется<br>• Данные реплицируются для отказоустойчивости<br>• Автоматический сплит при переполнении шарда<br>• Мердж при уменьшении нагрузки | • Шарды восстанавливаются из чекпоинтов<br>• WAL применяется к каждому шарду<br>• Балансировка после восстановления<br>• Автоматическое перераспределение |
| **Checkpoint / Snapshot** | **Read Committed** | • Периодическое сохранение снапшотов (каждые 5 мин)<br>• Атомарная запись с временным файлом<br>• Контрольная сумма для верификации<br>• Сжатие снапшотов (gzip)<br>• Хранение последних N чекпоинтов | • При сбое во время создания - временный файл удаляется<br>• Предыдущий чекпоинт остаётся целым<br>• Атомарное переименование гарантирует целостность<br>• WAL LSN сохраняется в чекпоинте | • Загрузка из последнего валидного чекпоинта<br>• Применение WAL после чекпоинта<br>• Проверка контрольной суммы при загрузке<br>• Автоматическое восстановление из чекпоинта |
| **WAL (Write-Ahead Log)** | **Persistent** | • Все записи сначала идут в WAL<br>• Segmented WAL с ротацией (64 MB)<br>• Пакетная запись с fsync<br>• CRC32 для верификации целостности<br>• Асинхронная запись с буферизацией | • При сбое - WAL сохраняет все записи<br>• fsync гарантирует запись на диск<br>• Segments позволяют восстанавливать частичные данные<br>• Индекс LSN для быстрого поиска | • Полное восстановление из WAL<br>• Асинхронный Recovery Manager<br>• Параллельное применение записей (4 воркера)<br>• Восстановление 2PC транзакций |
| **2PC (Distributed Transactions)** | **Read Committed** | • Двухфазный коммит для распределённых транзакций<br>• Состояния: Active → Prepared → Committed/Aborted<br>• Координатор отслеживает статус узлов<br>• Таймаут Prepared транзакций (10 сек) | • При сбое координатора - транзакция в Prepared состоянии<br>• Автоматический откат по таймауту<br>• Узлы могут завершить транзакцию автономно<br>• Pending транзакции сохраняются в WAL | • Восстановление pending 2PC транзакций<br>• Проверка таймаута при старте<br>• Автоматический откат просроченных транзакций<br>• Голосование узлов для завершения |
| **Deadlock Detection** | **N/A** | • Обнаружение циклических ожиданий<br>• Автоматический abort одной из транзакций<br>• Периодическая проверка (каждую секунду)<br>• Поддержка распределённых deadlock-ов | • При сетевых задержках - возможны ложные срабатывания<br>• Abort транзакции с последующим повтором<br>• Распределённый deadlock detection через координатор | • Deadlock граф восстанавливается из активных транзакций<br>• Автоматическое разрешение при старте<br>• Логирование deadlock-ов для анализа |
| **MVCC (Multi-Version Concurrency Control)** | **Repeatable Read** (внутри транзакции) | • Каждая запись хранит несколько версий<br>• Чтение получает версию на момент начала транзакции<br>• Автоматическая очистка старых версий (каждые 5 мин)<br>• Хранение до 100 версий на документ<br>• Retention: 7 дней | • Версии сохраняются в памяти и WAL<br>• При сбое - версии восстанавливаются из WAL<br>• Visibility Map ускоряет проверку видимости<br>• ReadTimestampCache для быстрого доступа | • Версии восстанавливаются из WAL записей<br>• Автоматическая очистка устаревших версий<br>• Восстановление Visibility Map<br>• Кеш перестраивается при загрузке |
### Условные обозначения:
| Символ | Значение |
|--------|----------|
| ✅ **Гарантировано** | Операция гарантирует консистентность при любых условиях |
| ⚠️ **Частично** | Требует дополнительных проверок или имеет ограничения |
| 🔄 **Автоматически** | Восстановление происходит без вмешательства пользователя |
| 📊 **Настраивается** | Поведение можно настроить через конфигурацию |
## Ключевые гарантии:
1. **ACID**: Все операции соответствуют ACID благодаря WAL + MVCC + 2PC
2. **Durability**: fsync + WAL гарантируют сохранность данных
3. **Consistency**: Чекпоинты + контрольные суммы + верификация
4. **Isolation**: MVCC + Read Committed + Repeatable Read внутри транзакций
5. **Availability**: Raft + репликация + автоматическое переизбрание лидера
6. **Partition Tolerance**: 2PC + таймауты + автоматический откат
> [!TIP] > [!TIP]
> WAL- это журнал предзаписи транзакций, который в субд **futriix** выполняет следующие действия: > WAL- это журнал предзаписи транзакций, который в субд **futriix** выполняет следующие действия:
> 1. Хранит все операции транзакций до их фиксации (INSERT, UPDATE, DELETE) > 1. Хранит все операции транзакций до их фиксации (INSERT, UPDATE, DELETE)
@@ -1662,7 +1714,7 @@ futriix:~> doc compression employees 550e8400-e29b-41d4-a716-446655440000
<p align="right">(<a href="#readme-top">К началу</a>)</p> <p align="right">(<a href="#readme-top">К началу</a>)</p>
## Дорожная карта ## План развития
- [x] Реализовать поддержку хранимых процедур - [x] Реализовать поддержку хранимых процедур
- [x] Реализовать поддержку триггеров (обратных вызовов) - [x] Реализовать поддержку триггеров (обратных вызовов)
@@ -1735,6 +1787,18 @@ futriix:~> doc compression employees 550e8400-e29b-41d4-a716-446655440000
- [x] Реализовать Прозрачное обновление схемы данных - [x] Реализовать Прозрачное обновление схемы данных
- [x] Реализовать в системе бекапов только "планировщик бэкапов" и "инкрементальность (на основе WAL)" - [x] Реализовать в системе бекапов только "планировщик бэкапов" и "инкрементальность (на основе WAL)"
- [x] Реализовать механизм плагинов, с помощью которого можно на языке lua реализовать движки для субд, не изменяя её исходный код - [x] Реализовать механизм плагинов, с помощью которого можно на языке lua реализовать движки для субд, не изменяя её исходный код
- [x] Реализовать атомарную запись через временный файл (Обеспечение целостности чекпоинтов (снапшотов) базы данных)
- [x] Реализовать контрольную сумму SHA-256 для чекпоинтов
- [x] Реализовать блокировку при восстановлении
- [x] Реализовать проверку целостности при загрузке
- [x] Реализовать вывод информации о восстановлении
- [x] Реализовать блокировку при восстановлении
- [x] Реализовать очистку WAL сегментов после бэкапа
- [x] Реализовать Проверку версии бэкапа
- [x] Реализовать статусы бэкапов (pending-running-completed-failed)
- [x] Реализовать атомарнуя запись бэкапов (Обеспечение целостности файлов бэкапов)
- [x] Реализована оптимизация ядра субд (удалён файл "/internal/storage/storage.go", методы "Storage" и "NewStorage" вынесены в "/internal/storage/engine.go")
- [x] Реализация записи "пакетами записи" для WAL-журнала (flushBatch)
- [ ] Реализовать Multi-Raft (Несколько независимых Raft групп для разных шардов) - [ ] Реализовать Multi-Raft (Несколько независимых Raft групп для разных шардов)
- [ ] Реализовать (Linearizable чтения) чтения через лидера с кворумом для строгой консистентности в кластере - [ ] Реализовать (Linearizable чтения) чтения через лидера с кворумом для строгой консистентности в кластере
- [ ] Реализовать Learner узлы узлы для репликации без права голоса (для бэкапов) - [ ] Реализовать Learner узлы узлы для репликации без права голоса (для бэкапов)
@@ -1757,6 +1821,16 @@ futriix:~> doc compression employees 550e8400-e29b-41d4-a716-446655440000
## Контакты ## Контакты
Григорий Сафронов - [E-mail](gvsafronov@yandex.ru) По вопросам эксплуатации, производительности и консультации по настройки конфигурации, просьба обращаться по контактам указанными ниже в данном разделе.<br>
**Обращаем ваше внимание, что личная почта — это технический контакт, предназначенный только для:**
* **Сообщений о критических уязвимостях (с подробным PoC)**
* **Предложений о сотрудничестве**
* **Преложений по улучшений futriix**
Обращаем ваше внимание, что письма без четко сформулированной темы, вопроса или предложения рассматриваться не будут.
Григорий Сафронов - [E-mail](gvsafronov@yandex.ru) <br>
Сообщество - [Сообщество Futriix](https://source.futriix.ru/gvsafronov/futriix/issues/new/choose)
<p align="right">(<a href="#readme-top">К началу</a>)</p> <p align="right">(<a href="#readme-top">К началу</a>)</p>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -227,6 +227,7 @@ func executeInsertWithTransaction(coll *storage.Collection, operationPart, dbNam
} }
if storage.HasActiveTransaction() { if storage.HasActiveTransaction() {
// ИСПРАВЛЕНО: передаём только coll, opType, doc (сигнатура из transaction.go)
if err := storage.AddToTransaction(coll, "insert", doc); err != nil { if err := storage.AddToTransaction(coll, "insert", doc); err != nil {
return err return err
} }

View File

@@ -94,10 +94,11 @@ func NewRepl(store *storage.Storage, coordinator *cluster.RaftCoordinator, logge
// registerCommands регистрирует все команды REPL // registerCommands регистрирует все команды REPL
func (r *Repl) registerCommands() { func (r *Repl) registerCommands() {
// Команды управления базами данных // Команды управления базами данных
r.commands["create database"] = &Command{ // ИСПРАВЛЕНО: заменено "slice database" на "create slice"
Name: "create database", r.commands["create slice"] = &Command{
Description: "Create a new database", Name: "create slice",
Handler: r.handleCreateDatabase, Description: "Create a new database (slice)",
Handler: r.handleCreateSlice,
} }
r.commands["drop database"] = &Command{ r.commands["drop database"] = &Command{
@@ -574,9 +575,10 @@ func (r *Repl) addToHistory(cmd string) {
// ========== Обработчики команд ========== // ========== Обработчики команд ==========
func (r *Repl) handleCreateDatabase(args []string) error { // ИСПРАВЛЕНО: переименован обработчик с handleSliceDatabase на handleCreateSlice
func (r *Repl) handleCreateSlice(args []string) error {
if len(args) < 1 { if len(args) < 1 {
return fmt.Errorf("usage: create database <name>") return fmt.Errorf("usage: create slice <name>")
} }
name := args[0] name := args[0]
@@ -584,7 +586,7 @@ func (r *Repl) handleCreateDatabase(args []string) error {
return err return err
} }
utils.PrintSuccess(fmt.Sprintf("Database '%s' created at %s", name, time.Now().Format("2006-01-02 15:04:05.000"))) utils.PrintSuccess(fmt.Sprintf("Slice '%s' created at %s", name, time.Now().Format("2006-01-02 15:04:05.000")))
return nil return nil
} }
@@ -2400,7 +2402,8 @@ func (r *Repl) handleHelp(args []string) error {
description string description string
}{ }{
"Database Management": { "Database Management": {
{"create database <name>", "Create a new database"}, // ИСПРАВЛЕНО: обновлена справка с "create slice" вместо "slice database"
{"create slice <name>", "Create a new database (slice)"},
{"drop database <name>", "Delete an existing database"}, {"drop database <name>", "Delete an existing database"},
{"use <database>", "Switch to a specific database"}, {"use <database>", "Switch to a specific database"},
{"show databases", "List all available databases"}, {"show databases", "List all available databases"},
@@ -2507,7 +2510,8 @@ func (r *Repl) handleHelp(args []string) error {
utils.Println("") utils.Println("")
utils.PrintInfo("Examples:") utils.PrintInfo("Examples:")
utils.Println(" create database test") // ИСПРАВЛЕНО: обновлены примеры с "create slice" вместо "slice database"
utils.Println(" create slice test")
utils.Println(" use test") utils.Println(" use test")
utils.Println(" create collection users") utils.Println(" create collection users")
utils.Println(" insert users name=John,age=30") utils.Println(" insert users name=John,age=30")

View File

@@ -455,12 +455,15 @@ func (c *Collection) Insert(doc *Document) error {
// Обновление индексов (wait-free) // Обновление индексов (wait-free)
c.updateIndexes(doc, true) c.updateIndexes(doc, true)
// Обновление метаданных // Обновление метаданных - ИСПРАВЛЕНО: добавлена блокировка для согласованности
c.docCount.Add(1) c.docCount.Add(1)
c.sizeBytes.Add(int64(len(data))) c.sizeBytes.Add(int64(len(data)))
c.mu.Lock()
c.metadata.DocumentCount = c.docCount.Load() c.metadata.DocumentCount = c.docCount.Load()
c.metadata.SizeBytes = c.sizeBytes.Load() c.metadata.SizeBytes = c.sizeBytes.Load()
c.metadata.UpdatedAt = time.Now().UnixMilli() c.metadata.UpdatedAt = time.Now().UnixMilli()
c.mu.Unlock()
// Аудит вставки документа // Аудит вставки документа
AuditDocumentOperation("INSERT", c.dbName, c.name, doc.ID, doc.GetFields()) AuditDocumentOperation("INSERT", c.dbName, c.name, doc.ID, doc.GetFields())
@@ -628,7 +631,9 @@ func (c *Collection) Update(id string, updates map[string]interface{}) error {
// Сохраняем обновлённый документ // Сохраняем обновлённый документ
c.docs.Store(id, newDoc) c.docs.Store(id, newDoc)
c.mu.Lock()
c.metadata.UpdatedAt = time.Now().UnixMilli() c.metadata.UpdatedAt = time.Now().UnixMilli()
c.mu.Unlock()
// Аудит обновления документа // Аудит обновления документа
AuditDocumentOperation("UPDATE", c.dbName, c.name, id, updates) AuditDocumentOperation("UPDATE", c.dbName, c.name, id, updates)
@@ -671,8 +676,10 @@ func (c *Collection) Delete(id string) error {
// Обновляем метаданные // Обновляем метаданные
c.docCount.Add(-1) c.docCount.Add(-1)
c.mu.Lock()
c.metadata.DocumentCount = c.docCount.Load() c.metadata.DocumentCount = c.docCount.Load()
c.metadata.UpdatedAt = time.Now().UnixMilli() c.metadata.UpdatedAt = time.Now().UnixMilli()
c.mu.Unlock()
return nil return nil
} }
@@ -698,8 +705,10 @@ func (c *Collection) PermanentDelete(id string) error {
// Обновляем метаданные // Обновляем метаданные
c.docCount.Add(-1) c.docCount.Add(-1)
c.mu.Lock()
c.metadata.DocumentCount = c.docCount.Load() c.metadata.DocumentCount = c.docCount.Load()
c.metadata.UpdatedAt = time.Now().UnixMilli() c.metadata.UpdatedAt = time.Now().UnixMilli()
c.mu.Unlock()
// Аудит физического удаления // Аудит физического удаления
AuditDocumentOperation("PERMANENT_DELETE", c.dbName, c.name, id, nil) AuditDocumentOperation("PERMANENT_DELETE", c.dbName, c.name, id, nil)
@@ -726,7 +735,9 @@ func (c *Collection) RestoreDeleted(id string) error {
c.addToIndexes(doc) c.addToIndexes(doc)
c.docs.Store(id, doc) c.docs.Store(id, doc)
c.mu.Lock()
c.metadata.UpdatedAt = time.Now().UnixMilli() c.metadata.UpdatedAt = time.Now().UnixMilli()
c.mu.Unlock()
// Аудит восстановления // Аудит восстановления
AuditDocumentOperation("RESTORE", c.dbName, c.name, id, nil) AuditDocumentOperation("RESTORE", c.dbName, c.name, id, nil)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff