Update README.md
This commit is contained in:
175
README.md
175
README.md
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user