tl; dr: Как мне лучше использовать кеш файловой системы для миллионов скриптовых запросов?Каждый вывод Logstash в ES запускает безболезненный скрипт, который вызывает запрос.Если запрос не кэшируется файловой системой (из-за отсутствия доступной оперативной памяти), считывание дискового ввода-вывода увеличивается.Как лучше оптимизировать?
- Версия Elasticsearch: 6.4.2
- JVM: openjdk 1.8.0_181
- Два узла, доступно всего 84 ГБ оперативной памяти системы
- Ввод 250 ГБ JSON три раза в месяц
- Диски представляют собой комбинацию SATA SSD (в raid 0) и NVMe
Я обрабатываю 250 ГБ журналов JSON через Logstashи вывод их Elasticsearch.Журналы ввода содержат ВЕСЬ множество дубликатов, поэтому безболезненный сценарий используется для проверки метки времени в журнале ввода по сравнению с тем, что уже есть в Elasticsearch.Если это новая отметка времени, то она добавляет отметку времени в массив.В противном случае ничего не происходит.
Проблема в том, что чем дальше идет обработка, тем медленнее идет индексация .И это НЕ медленное и постепенное снижение (см. Изображение ниже).В течение часа скорость возрастает с 18000 ep / s до 2000 ep / s.
Скорость индексации огромна, пока весь кэш файловой системы не будет использован .Я на самом деле сильно сократил JVM, чтобы дать кешу как можно больше памяти.Независимо от этого, в конечном итоге скорость индексации сильно падает, а затем IO диска заявляет о высокойсм. SDB (SSD nvme) тратит все свое время на чтение, а не на запись.
# iostat -m -x 5
avg-cpu: %user %nice %system %iowait %steal %idle
1.16 0.00 7.31 47.55 0.00 43.98
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sdb 1.20 64.87 12333.93 20.96 1275.55 0.43 211.51 144.78 11.73 11.71 18.40 0.08 100.10
Это пример входных данных:
{"timestamp":"1534023333", "hash":"1", "value":"something1"}
{"timestamp":"1534022222", "hash":"1", "value":"something1"}
{"timestamp":"1534011111", "hash":"1", "value":"something1"}
{"timestamp":"1534023333", "hash":"2", "value":"something2"}
{"timestamp":"1534022222", "hash":"2", "value":"something2"}
{"timestamp":"1534011111", "hash":"2", "value":"something2"}
Это примерВывод Logstash и безболезненный используемый скрипт:
output {
elasticsearch {
hosts => ["http://127.0.0.1:9200"]
index => "testing"
document_id => "%{[hash]}"
doc_as_upsert => true
script => 'if(ctx._source.timestamp.contains(params.event.get("timestamp")[0])) return true; else (ctx._source.timestamp.add(params.event.get("timestamp")[0]))'
action => "update"
retry_on_conflict=>5
}
}
Вопросы :
- Как лучше всего оптимизировать мой вариант использования?Каждый вывод Logstash в ES запускает безболезненный скрипт, который вызывает запрос.Если запрос не кэшируется файловой системой, то чтение диска IO увеличивается.Я понимаю, что мог бы просто добавить больше памяти, но в итоге мой набор данных будет больше 250 ГБ, и я не хочу использовать 200+ ГБ памяти каждый раз, когда я хочу выполнить большое количество индексации.
- Есть ли другой способ сделать то, что я хочу сделать?Могу ли я проиндексировать все данные, а затем Elasticsearch объединить документы, имеющие одинаковый идентификатор документа, но разные временные метки.Например, взять два документа с одинаковым идентификатором, которые имеют две разные версии, но разные значения меток времени (в массиве) и объединить их вместе?