Update README.md

This commit is contained in:
2026-06-12 17:01:23 +00:00
parent 4d8cc0f9f0
commit 98c60db447

175
README.md
View File

@@ -701,6 +701,181 @@ futriix:~> show sessions
Субд `futriix` является распределённой субд. Согласованность узлов в распределённом кластере определяется на основе Raft-консенсуса с автоматическими выборами лидера. Поддерживаются одноузловой (для запуска на одном узле, без организации кластера) и многокластерный режимы, репликация данных (синхронная/асинхронная), мастер-мастер репликация и health-мониторинг узлов.
Автомасштабирование реализовано на основе комбинированного алгоритма **Predictive Horizontal Autoscaler**.
**Полная блок-схема алгоритма**
```sh
┌─────────────────────────────────────────────────────────────┐
│ Цикл оценки (каждые 30 сек)
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 1. Сбор метрик со всех узлов │
│ - CPU, Memory, QPS, Latency, Storage │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 2. Расчёт композитной нагрузки для каждого узла │
node_load = Σ(metric/ threshold) * weight │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 3. Вычисление средней нагрузки по кластеру │
avg_load = Σ(node_load) / total_nodes │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 4. Прогнозирование (линейная регрессия на окне из N точек)
predicted_load = avg_load + slope │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 5. Проверка cooldown периодов │
if time_since_last_scale < cooldown → NoChange │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 6. Принятие решения │
if predicted_load > scale_up_threshold → ScaleUp │
if predicted_load < scale_down_threshold → ScaleDown │
else → NoChange │
└─────────────────────────────────────────────────────────────┘
┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ ScaleUp │ │ScaleDown │ │NoChange │
└──────────┘ └──────────┘ └──────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ 7a. Добавление │ │ 7b. Удаление │
│ узлов │ │ узлов │
│ │ │ │
nodes_to_add = │ │ nodes_to_remove │
│ ceil(ratio * N) │ │ = ceil(ratio*N)
└─────────────────┘ └─────────────────┘
```
**Основной алгоритм принятия решений**
```sh
Решение = f(текущая_нагрузка, прогнозируемая_нагрузка, история, cooldown)
```
**Базовый принцип:**
* Сравнение средневзвешенной нагрузки с двумя порогами (верхним и нижним)
* Учёт нескольких метрик с разными весами
* Использование скользящего окна для сглаживания выбросов
**Алгоритм расчёта нагрузки на узел**
Для каждого узла вычисляется композитный показатель нагрузки по формуле:
```sh
node_load = Σ (metric_value / metric_threshold) * metric_weight
─────────────────────────────────────────────────
Σ metric_weights
```
**Пример с весами по умолчанию:**
* CPU: 40% веса, порог 75%
* Memory: 30% веса, порог 80%
* QPS: 20% веса, порог 70%
* Latency: 10% веса, порог 65%
Если CPU = 90%, Memory = 85%, QPS = 80%, Latency = 50%:
```sh
CPU_score = (0.90 / 0.75) = 1.20
Memory_score = (0.85 / 0.80) = 1.0625
QPS_score = (0.80 / 0.70) = 1.1429
Latency_score = (0.50 / 0.65) = 0.7692
node_load = (1.20*0.4 + 1.0625*0.3 + 1.1429*0.2 + 0.7692*0.1) / 1.0 = 1.10
```
**Вывод из вышеуказанных данных: Перегрузка свыше 1.0 → нужно масштабирование**
**Алгоритм прогнозирования нагрузки (линейная регрессия)**
Используется метод наименьших квадратов для прогноза нагрузки на следующий период:
```sh
slope = (n*Σxy - Σx*Σy) / (n*Σx² - (Σx)²)
predicted = avg(y) + slope
```
Где:
* x - временные шаги (0, 1, 2, ...)
* y - исторические значения нагрузки
* n - размер окна (по умолчанию 10 точек)
**Пример прогнозирования:**
```sh
История нагрузки: [0.65, 0.68, 0.72, 0.75, 0.78, 0.82, 0.85, 0.88, 0.91, 0.95]
Тренд (slope) = ~0.033
Прогноз = 0.95 + 0.033 = 0.983
```
**Алгоритм определения количества узлов**
Добавление новых узлов в кластер (Scale Up) рассчитывается по формулам:
```sh
excess = current_load - scale_up_threshold
ratio = excess / scale_up_threshold
nodes_to_add = ceil(ratio * current_nodes)
```
Пример:
```sh
current_load = 1.25, threshold = 0.75, current_nodes = 4
excess = 1.25 - 0.75 = 0.50
ratio = 0.50 / 0.75 = 0.667
nodes_to_add = ceil(0.667 * 4) = ceil(2.668) = 3
```
Удаление новых узлов из кластера (Scale Up) рассчитывается по формулам:
```sh
deficit = scale_down_threshold - current_load
ratio = deficit / scale_down_threshold
nodes_to_remove = ceil(ratio * (current_nodes - 1))
```
**Алгоритм стабилизации (Anti-Flapping)**
Данный алгоритм необходим для предотвращения частых переключений масштабирования, основывается на **Скользящей средней**
```sh
stabilized_load = Σ(load[i]) / N, где N = stabilization_window / evaluation_interval
```
**Алгоритм выбора узлов для удаления (при Scale Down)**
При "масштабировании вниз"(при автоматическом удалении узлов из кластера) узлы выбираются согласно их приоритету:
```sh
priority_for_removal = f(
node.load, // чем ниже нагрузка, тем выше приоритет
node.age, // чем новее узел, тем выше приоритет
node.replica_count // чем меньше реплик, тем ниже приоритет
)
score_for_removal = (1 - node.load) * 0.6 +
(node_uptime_hours / max_uptime) * 0.4
```
```sh
# Просмотр статуса кластера (режим лидера)
futriix:~> status