From 98c60db44763f98f10284a49023e6ce16684f5f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=93=D1=80=D0=B8=D0=B3=D0=BE=D1=80=D0=B8=D0=B9=20=D0=A1?= =?UTF-8?q?=D0=B0=D1=84=D1=80=D0=BE=D0=BD=D0=BE=D0=B2?= Date: Fri, 12 Jun 2026 17:01:23 +0000 Subject: [PATCH] Update README.md --- README.md | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) diff --git a/README.md b/README.md index 721c2cb..52b2718 100644 --- a/README.md +++ b/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