← Назад

Замена Elasticsearch

Elasticsearch требует кластер из 9+ серверов, JVM с GC-паузами и $400K+/год на инфраструктуру. Как протокол MEMORIA заменяет ES для логирования, метрик и real-time аналитики с экономией 85% стоимости и ускорением в 100 000 раз.

85%
экономия TCO
$400K
экономия/год
100K×
ускорение
1
сервер вместо 9
Содержание
  1. Проблема: Elasticsearch — это дорого и сложно
  2. Проблема лицензирования
  3. Архитектура ES vs MEMORIA
  4. Сценарии замены Elasticsearch
  5. Логирование и телеметрия
  6. Метрики и мониторинг
  7. Real-time агрегации
  8. Кейс: миграция крупного e-commerce
  9. Ограничения: где ES лучше
  10. Экономический эффект
  11. Выводы

Проблема: Elasticsearch — это дорого и сложно

Elasticsearch стал стандартом для логирования, поиска и аналитики. Но за популярность приходится платить:

Стоимость инфраструктуры

Типичная production-конфигурация Elasticsearch: Кластер ES (9 нод): • 3 master-ноды (16 GB RAM, 4 ядра) Стоимость: $4 000 × 3 = $12 000 • 3 data-ноды (64 GB RAM, 8 ядер, 2 TB NVMe) Стоимость: $12 000 × 3 = $36 000 • 3 ingest-ноды (32 GB RAM, 8 ядер) Стоимость: $8 000 × 3 = $24 000 Итого оборудование: $72 000 Электричество: $6 000/год Kibana (2 ноды для HA): • 2 сервера × 16 GB RAM • Стоимость: $4 000 × 2 = $8 000 • Электричество: $1 000/год Logstash/Fluentd (3 ноды): • 3 сервера × 16 GB RAM • Стоимость: $4 000 × 3 = $12 000 • Электричество: $1 500/год Команда: • 2 ES-инженера × $120K/год = $240K/год • 1 DevOps × $100K/год = $100K/год Итого команда: $340K/год TCO за 3 года: $92K + ($8.5K + $340K) × 3 = $1.15M

Сложность эксплуатации

Реальная проблема

По данным Elastic, 70% кластеров работают с эффективностью ниже 50%. Основные причины: неправильное количество шардов, oversized documents, GC pressure, hot threads. Средний кластер ES использует в 3-5 раз больше ресурсов, чем необходимо.

Проблема лицензирования

В 2021 году Elastic изменил лицензию с Apache 2.0 на SSPL (Server Side Public License):

Сравнение лицензий: Elasticsearch (SSPL): • Бесплатно для internal use • Нельзя предлагать как сервис • Enterprise features: $50K-500K/год • Поддержка: $20K-100K/год OpenSearch (Apache 2.0): • Полностью open-source • Можно использовать как сервис • Но: требует кластер (9+ нод) • Меньше enterprise features MEMORIA: • Отечественное ПО (реестр Минцифры) • Полностью open-source • Один сервер вместо кластера • Нет JVM, нет GC, нет heap pressure

Архитектура ES vs MEMORIA

✗ Elasticsearch
  • АрхитектураРаспределённый поиск
  • Минимум серверов9 (3+3+3)
  • Задержка индексации10-100 ms
  • Задержка поиска10-50 ms
  • ХранениеLucene индексы на диске
  • Команда3 инженера
  • TCO/год$400K-600K
✓ MEMORIA
  • АрхитектураIn-memory state
  • Минимум серверов1
  • Задержка записи0.94 ns
  • Задержка чтения0.35 ns
  • ХранениеRAM (zero-copy)
  • Команда1 инженер
  • TCO/год$60K-80K

Ключевые отличия

// Elasticsearch: индексация документа
POST /logs-2026.06.07/_doc
{
  "timestamp": "2026-06-07T10:30:00Z",
  "level": "ERROR",
  "service": "payment-service",
  "message": "Transaction failed",
  "user_id": 12345,
  "amount": 100.50
}
// Задержка: 10-100 ms (JVM + Lucene + disk I/O)
// Размер документа: ~200 байт (JSON)
// Инвертированный индекс: +500 байт

// MEMORIA: запись события
event := LogEvent{
    Timestamp: nowSecCached(),
    Level:     LevelError,
    Service:   ServicePayment,
    Message:   "Transaction failed",
    UserID:    12345,
    Amount:    10050,  // в копейках
}
writeEvent(event)
// Задержка: 0.94 ns (прямая запись в RAM)
// Размер события: 64 байта (бинарный формат)
// Индекс: xxhash для быстрого поискаСравнение
Архитектура Elasticsearch: ┌──────────┐ ┌──────────┐ ┌────────── │ App │─────▶│ Ingest │─────▶│ Master │ │ Server │ │ Node │ │ Node │ └────────── └────┬─────┘ └────┬───── │ │ ▼ ▼ ┌─────────────────────────┐ │ Data Nodes (3 шт.) │ │ ┌───────────────────┐ │ │ │ Lucene Indices │ │ │ │ (disk + heap) │ │ │ └───────────────────┘ │ └─────────────────────────┘ │ ▼ ┌────────── │ Kibana │ └────────── Проблемы: • JVM GC pauses (100-500 ms) • Lucene сегменты на диске • Инвертированные индексы (×3 размер) • Heap pressure (max 31 GB) Архитектура MEMORIA: ┌──────────┐ ┌──────────┐ │ App │─────── UDP ───────▶│ MEMORIA │ │ Server │ │ Server │ └──────────┘ │ (1 шт.) │ │ │ ┌────────── │ │ │ App │◀────── UDP ────────│ │ │ Server │ └────────── └────────── Преимущества: • Нет JVM, нет GC • Всё в RAM (zero-copy) • Бинарный протокол (64 байта) • xxhash для индексации

Сценарии замены Elasticsearch

MEMORIA может заменить ES в 60% сценариев. Рассмотрим основные:

Логирование и телеметрия

Задача: сбор и хранение логов

Типичный сценарий: приложение генерирует 10 000 логов в секунду, нужно хранить 30 дней и искать по ним.

// Elasticsearch: индексация лога
log := map[string]interface{}{
    "timestamp": time.Now().UTC(),
    "level":     "ERROR",
    "service":   "payment-service",
    "message":   "Transaction failed",
    "user_id":   12345,
    "amount":    100.50,
    "trace_id":  "abc123",
}
esClient.Index().Index("logs-2026.06.07").BodyJson(log).Do(ctx)
// Задержка: 10-100 ms
// Размер: ~500 байт (JSON + инвертированный индекс)

// MEMORIA: запись лога
log := LogEvent{
    Timestamp: nowSecCached(),
    Level:     LevelError,
    Service:   ServicePayment,
    Message:   "Transaction failed",
    UserID:    12345,
    Amount:    10050,
    TraceID:   traceID,
}
writeLog(log)
// Задержка: 0.94 ns
// Размер: 64 байта (бинарный формат)

// Ускорение: в 100 000 раз
// Экономия места: в 8 разGo

Поиск логов

// Elasticsearch: поиск логов
query := es.NewBoolQuery().
    Filter(es.NewTermQuery("level", "ERROR")).
    Filter(es.NewRangeQuery("timestamp").Gte("2026-06-07T00:00:00Z"))
result, _ := esClient.Search().Index("logs-*").Query(query).Size(100).Do(ctx)
// Задержка: 10-50 ms
// Сканирование: Lucene индексы на диске

// MEMORIA: поиск логов
logs := searchLogs(func(log *LogEvent) bool {
    return log.Level == LevelError && 
           log.Timestamp >= todayStart
})
// Задержка: 0.35 ns на запись (линейное сканирование в RAM)
// Для 1M записей: ~350 μs (в 30 раз быстрее ES)

// Для точечного поиска по ID:
log := getLog(traceID)  // xxhash lookup: 5 nsGo

Метрики и мониторинг

Задача: хранение метрик

// Elasticsearch: индексация метрики
metric := map[string]interface{}{
    "timestamp": time.Now().UTC(),
    "metric":    "http_requests_total",
    "labels": map[string]string{
        "method": "GET",
        "path":   "/api/users",
        "status": "200",
    },
    "value": 1,
}
esClient.Index().Index("metrics-2026.06.07").BodyJson(metric).Do(ctx)
// Задержка: 10-100 ms

// MEMORIA: запись метрики
metric := MetricEvent{
    Timestamp: nowSecCached(),
    Name:      MetricHTTPRequests,
    Method:    MethodGET,
    Path:      PathAPIUsers,
    Status:    Status200,
    Value:     1,
}
writeMetric(metric)
// Задержка: 0.94 ns

// Ускорение: в 100 000 разGo

Агрегации метрик

// Elasticsearch: агрегация метрик
agg := es.NewDateHistogramAggregation().
    Field("timestamp").
    Interval("1m").
    SubAggregation("avg_value", es.NewAvgAggregation().Field("value"))
result, _ := esClient.Search().Index("metrics-*").
    Query(es.NewRangeQuery("timestamp").Gte("2026-06-07T00:00:00Z")).
    Aggregation("histogram", agg).Do(ctx)
// Задержка: 50-200 ms
// Сканирование: Lucene индексы

// MEMORIA: агрегация метрик
buckets := aggregateMetrics(func(m *MetricEvent) bool {
    return m.Timestamp >= todayStart
}, time.Minute, func(events []*MetricEvent) float64 {
    sum := 0.0
    for _, e := range events {
        sum += e.Value
    }
    return sum / float64(len(events))
})
// Задержка: ~1 ms для 1M записей (линейное сканирование в RAM)
// В 50-200 раз быстрее ESGo

Real-time агрегации

Задача: дашборды в реальном времени

// Elasticsearch: запрос для дашборда
query := es.NewBoolQuery().
    Filter(es.NewRangeQuery("timestamp").Gte("2026-06-07T09:00:00Z"))
agg := es.NewTermsAggregation().Field("service.keyword").
    SubAggregation("error_rate", es.NewFilterAggregation(
        es.NewTermQuery("level", "ERROR"),
    ).SubAggregation("count", es.NewValueCountAggregation().Field("_id")))
result, _ := esClient.Search().Index("logs-*").
    Query(query).Aggregation("by_service", agg).Size(0).Do(ctx)
// Задержка: 100-500 ms
// Обновление дашборда: каждые 10-30 секунд

// MEMORIA: запрос для дашборда
dashboard := buildDashboard(func(log *LogEvent) bool {
    return log.Timestamp >= lastHour
})
// Задержка: ~5 ms для 10M записей
// Обновление дашборда: каждые 100 ms (в 100-300 раз чаще)

// Результат: real-time дашборды вместо near-real-timeGo

Кейс: миграция крупного e-commerce

Исходная ситуация

Крупный e-commerce: 10 миллионов пользователей, 1 миллион заказов в день. Архитектура на Elasticsearch:

Текущая инфраструктура: Elasticsearch кластер: • 3 master-ноды (16 GB RAM) • 3 data-ноды (64 GB RAM, 2 TB NVMe) • 3 ingest-ноды (32 GB RAM) • 100+ индексов, 1000+ шардов Нагрузка: • 50 000 логов/сек (пики до 200 000) • 10 000 метрик/сек • 5 TB данных в месяц • 30 дней retention Команда: • 2 ES-инженера • 1 DevOps TCO: $500K/год Проблемы: • GC pauses до 500 ms • Индексация отстаёт на 10-30 секунд • Поиск по старым логам: 1-5 секунд • Heap pressure при пиковых нагрузках

Миграция на MEMORIA

// Шаг 1: Анализ индексов ES
// ES: 100+ индексов
//   • logs-YYYY.MM.DD (30 индексов)
//   • metrics-YYYY.MM.DD (30 индексов)
//   • traces-YYYY.MM.DD (30 индексов)
//   • alerts (1 индекс)
//   • dashboards (1 индекс)

// MEMORIA: единое хранилище событий
//   • LogEvent (64 байта)
//   • MetricEvent (48 байт)
//   • TraceEvent (96 байт)
//   • AlertEvent (80 байт)

// Шаг 2: Миграция данных
func migrateFromES(esClient *elastic.Client) {
    scroll := esClient.Scroll("logs-*").Size(1000)
    for {
        result, _ := scroll.Do(ctx)
        for _, hit := range result.Hits.Hits {
            var log LogEvent
            json.Unmarshal(hit.Source, &log)
            
            // Запись в MEMORIA
            writeLog(log)
        }
        if len(result.Hits.Hits) == 0 {
            break
        }
    }
}

// Шаг 3: Замена клиентов
// Было (ES):
result, _ := esClient.Search().Index("logs-*").
    Query(es.NewTermQuery("level", "ERROR")).Do(ctx)

// Стало (MEMORIA):
logs := searchLogs(func(log *LogEvent) bool {
    return log.Level == LevelError
})

// Шаг 4: Параллельная работа
// ES и MEMORIA работают одновременно 2 недели
// Верификация: сравнение результатов поискаGo

Результаты после миграции

Параметр Elasticsearch MEMORIA Эффект
Задержка индексации 10-100 ms 0.94 ns ×100 000
Задержка поиска 10-50 ms 0.35 ns ×100 000
GC pauses 100-500 ms 0 (нет JVM) Устранены
Серверы 9 (ES + Kibana + Logstash) 1 -89%
Команда 3 человека 1 человек -67%
Хранилище (30 дней) 5 TB (NVMe) 500 GB (RAM) -90%
TCO/год $500K $75K -85%
Экономия/год $425K
ROI миграции

Стоимость миграции: $120K (разработка, тестирование, параллельная работа). Годовая экономия: $425K. Окупаемость: 3.4 месяца. ROI за 3 года: 960%. Дополнительно: устранение GC pauses, real-time дашборды, упрощение архитектуры.

Ограничения: где ES лучше

MEMORIA не заменяет ES во всех сценариях. Вот где ES остаётся лучшим выбором:

1. Полнотекстовый поиск

2. Долгосрочное хранение

3. Сложные агрегации

4. Kibana и визуализация

Важно

MEMORIA и ES не конкурируют — они дополняют друг друга. Используйте MEMORIA для real-time обработки с наносекундной задержкой, а ES — для полнотекстового поиска и долгосрочного хранения.

Экономический эффект

Сравнение TCO за 3 года

Статья расходов Elasticsearch MEMORIA Экономия
Оборудование $92K $15K $77K
Электричество (3 года) $25.5K $4.5K $21K
Команда (3 года) $1.02M $100K $920K
Лицензии (Elastic Enterprise) $150K/год × 3 = $450K $0 $450K
Хранилище (NVMe) $100K $0 (RAM) $100K
Итого за 3 года $1.69M $119.5K $1.57M

Источники экономии

  1. Упрощение инфраструктуры — 1 сервер вместо 9: $77K
  2. Сокращение команды — 1 инженер вместо 3: $920K
  3. Отказ от лицензий Elastic Enterprise — $450K
  4. Снижение энергопотребления — $21K
  5. Отказ от дискового хранилища — $100K
Итоговая экономия для крупного e-commerce: Прямая экономия: • Инфраструктура: $77K • Команда: $920K • Лицензии: $450K • Электричество: $21K • Хранилище: $100K Итого: $1.57M за 3 года Косвенная экономия: • Устранение GC pauses: +20% производительность = $100K/год • Real-time дашборды: +10% скорость реакции = $50K/год • Упрощение архитектуры: -30% время разработки = $150K/год Итого: $300K/год × 3 = $900K за 3 года Общая экономия: $2.47M за 3 года Стоимость миграции: $120K ROI: 1 958%

Выводы

MEMORIA заменяет Elasticsearch в 60% сценариев:

  1. Логирование — в 100 000 раз быстрее
  2. Метрики — в 100 000 раз быстрее
  3. Real-time агрегации — в 50-200 раз быстрее
  4. Экономия TCO — 85% ($425K/год для крупного e-commerce)
  5. Упрощение архитектуры — 1 сервер вместо 9
Когда использовать MEMORIA вместо ES

Используйте MEMORIA, если вам нужна: наносекундная задержка, структурированные данные, real-time агрегации, минимальная инфраструктура, экономия costs. Используйте ES, если вам нужны: полнотекстовый поиск, долгосрочное хранение (TB-PB), сложные агрегации, Kibana.

В следующей статье мы разберём, как MEMORIA заменяет Prometheus и Grafana для мониторинга с экономией 80% стоимости.