Перейти к основному содержимому

Бенчмарки

Методология

Мы подготовили набор бенчмарков, которые постарались сделать максимально воспроизводимыми и детерминированными. Датасет, который использовался во время бенчмарков, детерминирован и состоит из 40 гигабайт (219 млн) структурированных логов в формате json.

Пример лога:

{
"@timestamp": 897484581,
"clientip": "162.146.3.0",
"request": "GET /images/logo_cfo.gif HTTP/1.1",
"status": 200,
"size": 1504
}

Local Deploy

Тесты запускались на AWS хосте c6a.4xlarge, который имеет следующую конфигурацию:

CPURAMDisk
AMD EPYC 7R13 Processor 3.6 GHz, 16 vCPU32 GiBGP3

Более подробно ознакомиться с тем, какие компоненты участвую в данном сьюте, какие настройки компонентов были выставлены и как его запускать, вы можете тут.

Ниже представлена информация о конфигурации локального кластера:

ContainerReplicasCPU LimitRAM Limit
seq-db (--mode single)148 GiB
elasticsearch148 GiB
file.d1-12 GiB

Результаты (write-path)

На синтетических тестах у нас получились следующие числа:

ContainerAvg. Logs/secAvg. ThroughputAvg. CPU UsageAvg. RAM Usage
seq‑db370,00048MiB/s3.3vCPU1.8GiB
elasticsearch110,00014MiB/s1.9vCPU2.4GiB

Отсюда видно, что при сопоставимых значений используемых ресурсов, seq-db показала пропускную способность, которая в среднем 3.4 раз выше, чем пропускная способность у Elasticsearch.

Результаты (read-path)

В оба хранилища был предварительно загружен одинаковый датасет (формат см выще). Тесты read-path запускались без нагрузки на запись.

Важные замечания по настройкам запросов в elasticsearch:

  • был отключен кеш запросов (request_cache=false)
  • был отключен подсчёт total hits (track_total_hits=false)

Тесты проводились при помощи утилиты Grafana k6, параметры запросов указаны в каждом из сценариев, а также доступны в папке benchmarks/k6.

Сценарий: поиск всех логов с оффсетами

В Elasticsearch в конфигурации по умолчанию ограничивает page_size*offset <= 10.000.

Параметры: запросы параллельно с 20 потоков в течение 10 секунд. Выбирается и подгружается случайная страница [1–50].

DBAvgP50P95
seq-db5.56ms5.05ms9.56ms
elasticsearch6.06ms5.11ms11.8ms

Сценарий status: in(500,400,403)

Параметры: 20 looping VUs for 10s

DBAvgP50P95
seq-db364.68ms356.96ms472.26ms
elasticsearch21.68ms18.91ms29.84ms

Сценарий request: GET /english/images/top_stories.gif HTTP/1.0

Параметры: 20 looping VUs for 10s

DBAvgP50P95
seq-db269.98ms213.43ms704.19ms
elasticsearch46.65ms43.27ms80.53ms

Сценарий: агрегация с подсчётом кол-ва логов с определённым статусом

Написан запрос c таким sql аналогом: SELECT status, COUNT(*) GROUP BY status.

Параметры: 10 запросов параллельно с 2 потоков.

DBAvgP50P95
seq-db16.81s16.88s16.10s
elasticsearch6.46s6.44s6.57s

Сценарий: минимальный размер лога каждого статуса

SQL-аналог: SELECT status, MIN(size) GROUP BY status.

Параметры: 5 итераций с 1 потока.

DBAvgP50P95
seq-db33.34s33.41s33.93s
elasticsearch16.88s16.82s17.5s

Сценарий : range запросы - выборка из 5000 документов

Параметры: 20 потоков, 10 секунд.

Выбирается случайная страница [1-50], на каждой странице по 100 документов.

DBAvgP50P95
seq-db406.09ms385.13ms509.05ms
elasticsearch22.75ms18.06ms64.61ms

K8S Deploy

Ниже представлена информация о конфигурации кластера:

ContainerCPURAMDisk
seq‑db (--mode store)Xeon Gold 6240R @ 2.40GHzDDR4 3200MHzRAID10, 4×SSD
seq‑db (--mode ingestor)Xeon Gold 6240R @ 2.40GHzDDR4 3200MHz
elasticsearch (master/data)Xeon Gold 6240R @ 2.40GHzDDR4 3200MHzRAID10, 4×SSD
file.dXeon Gold 6240R @ 2.40GHzDDR4 3200MHz

Далее мы выделили базовый набор полей, которые мы будем индексировать. Так как Elasticsearch по умолчанию индексирует все поля, мы создали индекс k8s-logs-index, который индексирует только ранее выбранное нами множество полей.

Конфигурация 1x1

В данной конфигурации использовались следующие настройки индексов:

curl -X PUT "http://localhost:9200/k8s-logs-index/" -H 'Content-Type: application/json' -d'
{
"settings": {
"index": {
"number_of_shards": "6",
"refresh_interval": "1s",
"number_of_replicas": "0",
"codec": "best_compression",
"merge.scheduler.max_thread_count": "2",
"translog": { "durability": "request" }
}
},
"mappings": {
"dynamic": "false",
"properties": {
"request": { "type": "text" },
"size": { "type": "keyword" },
"status": { "type": "keyword" },
"clientip": { "type": "keyword" }
}
}
}'

Ровно такую же конфигурацию индексирования и репликации мы задали и для seq-db.

Результат

ContainerCPU LimitRAM LimitAvg. CPUAvg. RAM
seq‑db (--mode store)1016GiB8.813.2GB
seq‑db (--mode proxy)68GiB4.924.9 GiB
elasticsearch (data)1632GiB15.1813GB
ContainerAvg. ThroughputLogs/sec
seq‑db181MiB/s1,403,514
elasticsearch61MiB/s442,924

Отсюда видно, что при сопоставимых значений используемых ресурсов, seq-db показала пропускную способность, которая в среднем ~2.9 раза выше, чем пропускная способность у Elasticsearch.

Конфигурация 6x6

Для данной конфигурации было поднято 6 нод seq-db в режиме --mode proxy и 6 нод в режиме --mode store.

Настройки индексов сохранились такими же, за исключением number_of_replicas=1:

curl -X PUT "http://localhost:9200/k8s-logs-index/" -H 'Content-Type: application/json' -d'
{
"settings": {
"index": {
"number_of_shards": "6",
"refresh_interval": "1s",
"number_of_replicas": "1",
"codec": "best_compression",
"merge.scheduler.max_thread_count": "2",
"translog": { "durability": "request" }
}
},
"mappings": {
"dynamic": "false",
"properties": {
"request": { "type": "text" },
"size": { "type": "keyword" },
"status": { "type": "keyword" },
"clientip": { "type": "keyword" }
}
}
}'

Results

ContainerCPU LimitRAM LimitReplicasAvg. CPU (per instance)Avg. RAM (per instance)
seq‑db (--mode proxy)38GiB61.872.2GiB
seq‑db (--mode store)1016GiB67.402.5GiB
elasticsearch (data)1332GiB67.348.8GiB
ContainerAvg. ThroughputAvg. Logs/sec
seq‑db436MiB/s3,383,724
elasticsearch62MiB/s482,596