В последние пол года довольно много пришлось заниматься ElasticSearch. За это время многое о нем у знал, многое понял. Решил поделится со всеми своими открытиями.
Первое и наверное самое главное. Обновления в ElasticSearch не real time. Под капотом там старые добрые lucene индексы, которые как были append-only так ими и остались. ElasticSearch очень крут тем что тебе не надо самому организовывать эту псевдо-реалтаймовость обновления индексов. Он сразу предоставляет тебе абстракции базы данных (get/update/delete), и дефолтное значение refresh_interval=1s некоторое время поддерживает данную иллюзию. Но во первых 1s время обновление это не реалтайм не разу, во вторых опыт показывает что при большой нагрузке эластик с таким refresh_interval очень плохо себя чувствует. Вы будете вынуждены либо группировать апдейты у себя в коде либо увеличивать refresh_interval.
Второе: оптимальный размер jvm heap для эластика примерно половина доступной оперативки. Вторую половину оперативки он использует неявно, через кэши операционной системы.
Третье:
ElasticSearch очень чувствителен к сетевым проблемам. Как только случается сетевая задержка большая чем
zen.discovery.timeout нода отваливается от кластера. Через секунду она снова присоеденится к кластеру и начнет процесс восстановления. Будет скачивать с других нод шарды которые раньше на ней находились. Причем делает это
ElasticSearch в несколько потоков чем очень не слабо нагружает кластер. Настолько не слабо что часто это приводит к тому что весь кластер складывается как карточный домик. Просто из-за того что сеть мигнула на одном из серверов. Возможно вам стоит ограничить количество шард которые
ElasticSearch будет восстанавливать одновременно. Чем меньше параллельных потоков - тем меньше нагрузка на другие ноды. И тем больше время требуемое на присоединение ноды обратно. И обязательно посмотрите на
zen.discovery.timeout - это значение должно соответствовать качеству вашей сети.
Четвертое: я бы очень НЕ рекомендовал вам использовать ноды с разной пропускной способностью в одном кластере. Эластик исходит из того что все ноды одинаковые и распределяет нагрузку соответствующим образом. То есть размеры шард, их распределение по нодам. Как только самая слабая нода в кластере перестает справляться со своей нагрузкой - весь кластер встает колом. Если есть какая-то слабая нода - лучше либо вообще отцепить ее от кластера либо сделать ее вспомогательной нодой (не хранящей данные).
Пятое: важно выбрать правильный баланс между количеством реплик и затратами на обновление индекса и восстановлением кластера. Чем больше у вас реплик - тем большее время потребуется на восстановление кластера и тем больше ресурсов будут затрачивать обновление индексов.
Шестое: Не питайте напрасных надежд - ElasticSearch это не база данных. Он не должен быть primary хранилищем данных. Смело ставьте action.write_consistency: one. Это очень сильно ускорит выполнение обновлений индекса.
Седьмое: Ограничте размер threadpool.search.queue_size. Если кластеру плохо, то есть скорость обработки запросов сильно меньше скорости их выполнения какая бы ни была очередь - она наполняется моментально. Если эта очередь большая - она только отъесть оперативную память, которой и так не хватает в такие моменты. Мы прекрасно живем с threadpool.search.queue_size: 500 и примерно 30 000rps.
Восьмое: обратите внимание на
field data cache Его построение это очень затратная операция, если у вас интенсивно наполняется сбрасывается этот кэш - производительность будет очень страдать. Еще советую посмотреть на использование doc_value - возможно это избавит вас от многих проблем с памятью.
Девятое: обратите внимание сколько аггрегаций делается в запросах к ElasticSearch. Аггрегации это довольно затратная операция, если есть способ уменьшить их количество - это сильно уменшит время выполнения запроса.
Десятое: про marvel наверное все знают, думаю нет смысла писать что это must have. Но кроме него есть еще один очень полезный плагин для
ElasticSearch - HQ