Автор иллюстрации — Anton Gudim


«Подготовленный человек тоже наступает на грабли.
Но с другой стороны — там, где ручка.»


Elasticsearch — прекрасный инструмент, но каждый инструмент требует не только настройки и ухода, но и внимания к мелочам. Некоторые — незначительны и лежат на поверхности, а другие спрятаны так глубоко, что на поиск уйдет не один день, не один десяток кружек кофе и не один километр нервов. В этой статье расскажу про девять замечательных граблей в настройке эластика, на которые я наступил.

Я расположу грабли по убыванию очевидности. От тех, которые можно предусмотреть и обойти на этапе настройки и ввода кластера в production state, до весьма странных, но приносящих самый большой опыт (и звёзды в глазах).

Data-ноды должны быть одинаковыми


«Кластер работает со скоростью самой медленной дата-ноды» — выстраданная аксиома. Но есть ещё один очевидный момент, не связанный с производительностью: эластик мыслит не дисковым пространством, а шардами, и старается равномерно распределить их по дата-нодам. Если на какой-то из дата-нод больше места, чем на других, то оно будет бесполезно простаивать.

Deprecation.log


Может случиться, что кто-то пользуется не самым современным средством отправки данных в эластик, которое не умеет ставить Content-Type при выполнении запросов. В этом списке, например, heka, или когда логи уходят с устройств их встроенными средствами). В таком случае deprecation. log начинает расти с устрашающей скоростью, и на каждый запрос в нём появляются такие строчки:

[2018-07-07T14:10:26,659][WARN ][o.e.d.r.RestController] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header.
[2018-07-07T14:10:26,670][WARN ][o.e.d.r.RestController] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header.
[2018-07-07T14:10:26,671][WARN ][o.e.d.r.RestController] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header.
[2018-07-07T14:10:26,673][WARN ][o.e.d.r.RestController] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header.
[2018-07-07T14:10:26,677][WARN ][o.e.d.r.RestController ] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header.

Запросы приходят, в среднем, каждые 5-10 мс — и каждый раз в лог добавляется новая строчка. Это негативно влияет на производительность дисковой подсистемы и увеличивает iowait. Deprecation.log можно выключить, но это не слишком разумно. Чтобы собирать логи эластика в него же, но не допускать замусоривания, я отключаю только логи класса o.e.d.r.RestController.

Для этого нужно добавить в logs4j2.properties такую конструкцию:

logger.restcontroller.name = org.elasticsearch.deprecation.rest.RestController
logger.restcontroller.level = error

Она повысит логи этого класса до уровня error, и они перестанут попадать в deprecation.log.

.kibana


Как выглядит обычный процесс установки кластера? Ставим ноды, объединяем их в кластер, ставим x-pack (кому нужен), ну и конечно, Kibana. Запускаем, проверяем, что всё работает и Кибана видит кластер, и продолжаем настройку. Проблема в том, что на свежеустановленном кластере шаблон по умолчанию выглядит примерно так:

{
	"default": {
		"order": 0,
		"template": "*",
		"settings": {
			"number_of_shards": "1",
			"number_of_replicas": "0"
		}
	},
	"mappings": {},
	"aliases": {}
}

И индекс .kibana, где хранятся все настройки создаётся в единственном экземпляре.

Как-то был случай, когда из-за аппаратного сбоя полегла одна из дата-нод в кластере. Он довольно быстро пришел в консистентное состояние, подняв реплики шард с соседних дата-нод, но, по счастливому совпадению, именно на этой дата-ноде располагался единственный шард с индексом .kibana. Ситуация патовая — кластер живой, в рабочем состоянии, а Kibana в red-статусе, и у меня разрывается телефон от звонков сотрудников, которым срочно нужны их логи.

Решается всё это просто. Пока ещё ничего не упало:

XPUT .kibana/_settings
{
	"index": {
		"number_of_replicas": "<количество_дата_нод>"
	}
}

XMX/XMS


В документации написано — «No more than 32 GB», и это правильно. Но также правильно и то, что не нужно устанавливать в настройках сервиса
-Xms32g
-Xmx32g

Потому что это уже больше чем 32 гигабайта, и тут мы упираемся в интересный нюанс работы Java с памятью. Выше определённого предела Java перестаёт использовать сжатые указатели и начинает потреблять неоправданно много памяти. Проверить, использует ли сжатые указатели Java-машина с запущенным Elasticsearch, очень просто. Смотрим в лог сервиса:

[2018-07-29T15:04:22,041][INFO][o.e.e.NodeEnvironment][log-elastic-hot3] heap size [31.6gb], compressed ordinary object pointers [true]

Объем памяти, который не стоит превышать, зависит, в том числе, от используемой версии Java. Чтобы вычислить точный объем в вашем случае — смотрите документацию.

У меня сейчас на всех дата-нодах эластика установлено:

-Xms32766m
-Xmx32766m

Вроде бы банальный факт, и в документации хорошо описан, но регулярно в работе сталкиваюсь с инсталляциями Elasticsearch, где этот момент упущен, и Xms/Xmx выставлены в 32g.

/var/lib/elasticsearch


Это путь по-умолчанию для хранения данных в elasticsearch. yml:

path.data: /var/lib/elasticsearch

Туда я обычно монтирую один большой RAID массив, и вот почему: указываем ES несколько путей для хранения данных, например, так:

path.data: /var/lib/elasticsearch/data1, /var/lib/elasticsearch/data2

В data1 и data2 смонтированы разные диски или raid-массивы. Но эластик не делает балансировки и не распределяет нагрузку между этими путями. Сначала он заполняет один раздел, потом начинает писать в другой, поэтому нагрузка на хранилища будет неравномерной. Зная это, я принял однозначное решение — объединил все диски в RAID0/1 и смонтировал его в путь, который указан в path.data.

available_processors


И нет, я сейчас имею в виду не процессоры на ingest-нодах. Если заглянуть в свойства запущенной ноды (через _nodes API), можно увидеть примерно такое:

"os". {
	"refresh_interval_in_millis": 1000,
	"name": "Linux",
	"arch": "amd64",
	"version": "4.4.0-87-generic",
	"available_processors": 28,
	"allocated_processors": 28
}

Видно, что нода запущена на хосте с 28 ядрами, а эластик правильно определил их количество и запустился на всех. Но если ядер больше 32, то иногда бывает так:

"os": {
	"refresh_interval_in_millis": 1000,
	"name": "Linux",
	"arch": "amd64",
	"version": "4.4.0-116-generic",
	"available_processors": 72,
	"allocated_processors": 32
}

Приходится принудительно выставлять количество доступных сервису процессоров — это хорошо сказывается на производительности ноды.

processors: 72

thread_pool.bulk.queue_size


В разделе про thread_pool.bulk.rejected прошлой статьи была такая метрика — счётчик количества отказов по запросам на добавление данных.

Я писал о том, что рост этого показателя — очень плохой признак, и разработчики рекомендуют не настраивать пулы тредов, а добавлять в кластер новые ноды — якобы, это решает проблемы с производительностью. Но правила нужны и для того, чтобы иногда их нарушать. Да и не всегда получается «забросать проблему железом», поэтому одна из мер борьбы с отказами в bulk запросах — поднять размеры этой очереди.

По умолчанию настройки очереди выглядят так:

"thread_pool":
{
	"bulk": {
		"type": "fixed",
		"min": 28,
		"max": 28,
		"queue_size": 200
	}
}

Алгоритм такой:

  1. Собираем статистику по среднему размеру очереди в течение дня (мгновенное значение хранится в thread_pool.bulk.queue);
  2. Аккуратно увеличиваем queue_size до размеров чуть больших, чем средний размер активной очереди — потому что отказ возникает при его превышении;
  3. Увеличиваем размер пула — это не обязательно, но приемлемо.

Для этого добавляем в настройки хоста что-то наподобие такого (значения у вас, конечно, будут свои):

thread_pool.bulk.size: 32
thread_pool.bulk.queue_size: 500

И после перезапуска ноды обязательно мониторим нагрузку, I/O, потребление памяти. и всё что можно, чтобы при необходимости откатить настройки.

Важно: эти настройки имеют смысл только на нодах работающих на приём новых данных.

Предварительное создание индексов


Как я говорил в первой статье цикла, мы используем Elasticsearch для хранения логов всех микросервисов. Суть проста — один индекс хранит логи одного компонента за один день.

Из этого следует, что каждые сутки создаются новые индексы по числу микросервисов — поэтому раньше каждую ночь эластик впадал в клинч примерно на 8 минут, пока создавалась сотня новых индексов, несколько сотен новых шардов, график нагрузки на диски уходил «в полку», вырастали очереди на отправку логов в эластик на хостах, и Zabbix расцветал алертами как новогодняя ёлка.

Чтобы этого избежать, по здравому размышлению был написан скрипт на Python для предварительного создания индексов. Скрипт работает так: находит индексы за сегодня, извлекает их маппинги и создаёт новые индексы с теми же маппингами, но на день вперёд. Работает по cron, запускается в те часы, когда Эластик наименее загружен. Скрипт использует библиотеку elasticsearch и доступен на GitHub.

Transparent Huge Pages


Как-то раз мы обнаружили, что ноды эластика, которые работают приём данных, начали зависать под нагрузкой в пиковые часы. Причём с очень странными симптомами: использование всех процессорных ядер падает до нуля, но тем не менее сервис висит в памяти, исправно слушает порт, ничего не делает, на запросы не отвечает и через какое-то время вываливается из кластера. На systemctl restart сервис не реагирует. Помогает только старый-добрый kill ?9.

Стандартными средствами мониторинга это не отлавливается, на графиках до самого момента падения штатная картина, в логах сервиса — пусто. Дамп памяти java-машины в этот момент сделать тоже не удавалось.

Но, как говорится, «мы же профессионалы, поэтому спустя какое-то время нагуглили решение». Похожая проблема освещалась в треде на discuss.elastic.co и оказалась багом в ядре, связанным с tranparent huge pages. Решилось всё выключением thp в ядре, с помощью пакета sysfsutils.

Проверить, включены ли у вас transparent huge pages, просто:

cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]

Если там стоит [always] — вы потенциально в опасности.

Заключение


Это основные грабли (на деле их было, конечно, больше), на которые мне довелось наступить за полтора года работы в качестве администратора кластера Elasticsearch. Надеюсь, эта информация пригодится вам на сложном и загадочном пути к идеальному кластеру Elasticsearch.

А за иллюстрацию спасибо Anton Gudim — в его инстаграме еще много хорошего.

Комментарии (56)


  1. divanikus
    22.08.2018 14:29

    Не подскажите, никаких тулзов для архивирования снэпшотов еще не придумали? У меня есть задача хранить много толстых индексов (сотни гигабайт в день) длительное время. Какое-то количество «горячих» индексов живет в кластере, а старые постепенно по одному снэпшотятся и удаляются из кластера. В старых эластиках можно было легко папку со снэпшотом пожать и убрать в куда-то еще более медленное и дешевое место, а вот с 5.х там уже все сложнее. А бесконечно наращивать сторадж тоже не вариант.


    1. adel-s Автор
      22.08.2018 14:31

      Увы, в связи с нашей спецификой использования эластика — снапшоты мы не делаем.


    1. chupasaurus
      22.08.2018 14:40

      Я сейчас делаю это так:

      1. Подключаю репозиторий-директорию для снепшотов
      2. Создаю по снепшоту на каждый индекс
      3. Отключаю репозиторий снепшотов
      4. Создаю архив с репой. Особо не тестил разные алгоритмы сжатия, LZMA пока устраивает.
      5. Очищаю директорию от сырых снапшотов
      6. Отправляю файл с архивом в долгий ящик

      Если дадут разрешение (NDA), то свой скрипт выложу под MIT.


      1. divanikus
        22.08.2018 14:43

        Да там по сути формат несложный, индекс файлик и набор папок. Индекс это просто json. По нему можно как разобрать, так и собрать снэпшоты по частям. Но не хочется изобретать велосипед, если кто-то уже сделал. У меня к сожалению ваша схема не прокатит, каталог снэпшотов 30 ТБ.


        1. chupasaurus
          22.08.2018 14:51

          К сожалению, нельзя вытянуть отдельные снэпшоты из каталога (ссылка).


          1. divanikus
            22.08.2018 16:38

            В моем случае это не совсем так, так как индекс снэпшотится лишь единожды. Т.е. кусок вытащить можно.


            1. vladimir_dolzhenko
              22.08.2018 17:36

              в частном случае да, но в общем случае snapshot'ы инкрементальны


              1. divanikus
                22.08.2018 18:35

                Это все равно не мешает их разбирать по кускам, если что. Если эластик сам может, то и сторонняя утилита тоже.


                1. vladimir_dolzhenko
                  22.08.2018 18:43

                  Понятно, что может — никто из этого никого секрета не делает — open source же. Я про то, что из коробки нельзя вытащить отдельные файлы snapshot'а — в силу специфики Lucene там могут оказаться куски предыдущего snapshot'а, которые мешать не будут, но будут занимать место.

                  Забавно, но буквально сегодня клиент спрашивал — как вытащить последний snapshot из кучи. Может стоит оформить ticket?


  1. eaa
    22.08.2018 14:34

    Может сталкивались с задачей склеить два индекса в один? Как решали? Насколько я понимаю, штутных средств эластик не предоставляет.


    1. adel-s Автор
      22.08.2018 14:42

      Не сталкивался, но «в лоб» решил бы через logstash. Завернуть его на один кластер: читать из двух индексов, складывать в один. Главное проверить чтобы маппинги совпадали.
      Может есть еще какое-то решение, не уверен.


      1. chupasaurus
        22.08.2018 14:53

        А даже если маппинги не совпадают, можно придумать схему миграции конфликтующих полей и в пайплане LS разруливать.


        1. divanikus
          22.08.2018 16:37

          В elasticdump можно указать transform для таких случаев. Индексы правда лучше создать заранее с правильными маппингами, потому что копирует их оно так себе.


    1. divanikus
      22.08.2018 14:42

      elasticdump


    1. DerNitro
      23.08.2018 10:04

      Мы используем алиасы.


      1. alexdoesh
        23.08.2018 16:33

        И это, имхо, самое верное с точки зрения идеологии решение. Только помнить, что писать в алиас поверх >1 индекса нельзя.


  1. chemtech
    22.08.2018 16:58

    Спасибо за статью!
    Подскажите пожалуйста.
    У нас используется ELK 5.6.8. В ELK 6 написано: Multiple mapping types are not supported in indices created in 6.0
    Как определить какие типы данных относятся к Multiple mapping types?
    Есть ли возможность проверить что ничего не сломается при обновлении с 5.6.8 до 6?
    Есть ли возможность откатиться назад?
    И самое главное есть ли смысл переходить?


    1. morr
      22.08.2018 17:42

      > И самое главное есть ли смысл переходить?
      Если вам нужны какие-то фичи, появившиеся в 6й ветке. Иначе смысла мало, потратите кучу времени, и ничего не выиграете в итоге. 6я версия обратно не совместима с 5й.

      Лично я обновлялся только из-за появившейся возможности задания кастомной функции tfidf для вычисления similarity в индексах.


      1. vladimir_dolzhenko
        22.08.2018 17:49

        В каком смысле

        6я версия обратно не совместима с 5й.
        ?

        Есть ломающие изменения (breaking changes), которые опять-таки описаны — но в целом 6ка должна читать индексы 5ки.


        1. morr
          22.08.2018 18:07

          Есть ломающие изменения (breaking changes), которые опять-таки описаны — но в целом 6ка должна читать индексы 5ки.

          Да, там в целом всё работает, но натыкаешься на разные мелочи.
          Что-то, что было deprecated, убрали, что-то поменяли, например при создании индекса вместо "index": "not_anylyzed" параметр теперь передаётся как "index": false. Другие подробности не вспомню, апгрейд довольно давно делал.
          Но эти мелочи выливаются в то, что нельзя просто взять и обновить на серверах эластик, нужно ещё править код своих проектов, и, если используются сторонние библиотеки, то в некоторых случаях и код этих библиотек обновлять.


          1. vladimir_dolzhenko
            22.08.2018 18:11

            Согласен, но в целом ES уделяет большое внимание backward-compatibility, и braking changes по возможности делать как можно меньше — если только уже совсем никак. Но и старый воз костылей не хочется ни тащить, ни поддерживать.


    1. divanikus
      22.08.2018 18:38

      Multiple mappings types означает что больше нельзя в одном индексе несколько типов иметь. Например myindex/users, myindex/sessions. Раньше так можно было, теперь — нет. Созданные до перехода на 6.х индексы будут работать, а вот новые такие уже не создать.


  1. usego
    22.08.2018 17:21

    А проблему создания в полночь тыквы, т.е. новых индексов не пробовали решать переходом c yyyy.mm.dd-index схемы на роллап? У меня не так много индексов, но старые индексы ночью мигрируют с hot нод на warm и это тоже доставляет, вот подумываю роллап попробовать, что бы новы ихдекс создавался только при переполнении старого, кроме этого может быть количество шардов уменьшится…


    1. adel-s Автор
      22.08.2018 20:43

      Да много чего по кластеру надо делать, сервис (в его нынешней конфигурации), существует уже восемь месяцев, изменения назрели. Но это буду делать, увы, уже не я.
      Миграция шард — да, это головная боль. В среднем миграция данных за одни сутки занимает около 8 часов. И хоть гоняется ночью, но к утреннему росту нагрузки уж еле-еле поспевает.


  1. vladimir_dolzhenko
    22.08.2018 17:47
    -1

    Про 32Гб достаточно подробно описано в документации и о том насколько именно надо быть меньше 32х Гб даже в зависимости от версии java.


  1. ladutsko
    22.08.2018 18:11

    Как повлияло на производительность выключение thp?


    1. adel-s Автор
      22.08.2018 18:13

      Никак. Только зависать перестало.


  1. Ruslan_Y
    22.08.2018 19:07

    Из похожих «внезапных» проблем:

    1. Неочевидный лимит на число документов на шард (не более 2 147 483 647 документов) .
    2. Странное поведение, когда несколько инстансов эластика на 1 сервере работают быстрее чем один (на тех же CPU и дисках, у нас магическая цифра 25 тыс документов в секунду на 1 датаноду).
    3. Если по каким-то причинам маппинг на индекс не применился по темплейту и эластик его придумал сам (авто маппинг), самые необычные глюки при последующем поиске в данных между нормальными и «странными индексами». Хотя данные в _source выглядят идентично


    1. adel-s Автор
      22.08.2018 20:22

      Огогошеньки у вас объемы! Спасибо, про лимит на шард не знал.
      Записал в книжечку.

      По. п.2 — посмотрите на numactl. Возможно там собака зарыта.


    1. vladimir_dolzhenko
      22.08.2018 20:51

      Про лимит документов — это общая проблема Lucene-based движков. Elastic в этом не одинок.


    1. DerNitro
      23.08.2018 10:13

      Если по каким-то причинам маппинг на индекс не применился по темплейту и эластик его придумал сам (авто маппинг), самые необычные глюки при последующем поиске в данных между нормальными и «странными индексами». Хотя данные в _source выглядят идентично

      + объем данных индексов почти в 2 раза больше(на наших инсталляциях), помогает _reindex


  1. sberdyshev
    22.08.2018 19:11

    Добрый день.
    Статья отличная, спасибо!
    Скажите, вы используете curator? Я предполагал, что предварительное создание индексов как раз ему под силу.


    1. adel-s Автор
      22.08.2018 19:13

      Нет, не используем, но это отличная вещь, рекомендую. Сам не использовал, мне было интересно написать скрипты обслуживания самому :)


      1. sberdyshev
        22.08.2018 19:16

        А почему отказались от него, если не секрет?)


        1. adel-s Автор
          22.08.2018 19:23

          Не то чтобы «отказались», а просто не начинали. Интересно было самому в деталях реализации разобраться, прежде чем стандартные инструменты использовать. Но к нему все придет, да.


  1. sberdyshev
    22.08.2018 19:35

    В вашей соседней статье (к сожалению, пока не могу ее комментировать) приводятся данные по мощности серверов. Возникли вопросы:
    Как вы пришли к такому сайзингу (в особенности памяти для data узлов)? Опытным путем?
    Какой % памяти на data ноде отдаете под heap? 50%?
    Зачем такие мощные mater ноды?


    1. adel-s Автор
      22.08.2018 20:18

      1. Память для дата-нод выделяли сразу по максимуму — 32 гб. И то не хватает периодически. Была мысль попробовать перейти на 64 гб с использованием другого GC (Shenandoah), но руки не дошли и, боюсь, что уже не дойдут. А вот для клиентских нод (в которые смотрит Kibana), подбирали опытным путем, да. Через некоторое время дошли до 24 гб и на этом остановились.
      2. «Какой % памяти на data ноде отдаете под heap? 50%?» — вопроса не понял, уточните, пожалуйста.
      3. Это старая конфигурация. Она уже была, когда я пришел в компанию и получил в руки то, что получил. В следующей статье, я рассказывал как кластер переделывался под бОльшую оптимизацию ресурсов. Там я разместил все в LXC контейнеры и на каждый железный сервер влезло 2 дата-ноды + 1 мастер. И средствами LXC контейнеры лимитировались по процессорным ядрам — мастерам отдавалось по чуть-чуть, остальное уходило дата-нодам.
      Но и это уже старая конфигурация. Потом я перевел кластер на hot/warm архитектуру и там все опять поменялось :)


    1. divanikus
      23.08.2018 01:00

      Читайте основную доку: www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html

      За себя могу сказать, что желание поднять размер хипа повыше возникает очень быстро, но реально жить можно как и оговорено в статье, когда хип не более 50% от оперативной памяти.


    1. adel-s Автор
      23.08.2018 11:17

      А, вот теперь я понял что вы имели в виду «Какой % памяти на data ноде отдаете под heap? 50%?»
      Отвечаю — дата-нодам мы выдаем 32 гб. А сервера под дата-ноды закупаем с 64-128 (что чаще) Гб памяти на борту. У нас объемы такие, что дата-нодам отдаем максимум того, что они могут использовать.


  1. FYR
    23.08.2018 11:08
    +2

    Еще добавим грабелек:

    Для любого незакрытого индекса на диске требуется оперативная память как минимум 0,1% -0,5% (зависит от маппинга и используемых фич) от объема это индекса на диске. Просто для открытия шардов. Что в купе с требованием про HEAP_SIZE < 32g и тем что хип нужен не только чтобы индексы открыть — приводит к ограничению 16 — 24 ТБ индекса на одной ноде. Дальше придется городить огород с несколькими инстансами на сервер. Причем это еще без всяких сложных запросов.

    Очень долгая миграция шардов с узла на узел. Гораздо быстрее «холодные» индексы закрыть, потом rsync скопировать а потом открыть. Но удается это не очень всегда.

    Размер кластера ограничен количеством шардов в нем. На практике с ростом числа индексов и шардов просто катастрофически увеличивается время создания новых индексов. Причем в старых версиях просто больше 3х узлов при 20 тысячах индексов (пара шардов на каждый). В новых версиях лучше.

    Если активно используете scroll|scan см пункт первый. Ибо scroll_id включает в себя идентификаторы всех шард на которых хоть что-то нашлось пригодное для скана. У нас он достигал значений в сотни мегабайт на кластере из 20-30 узлов с сотней тысяч индексов.

    Частично помогла группировка узлов в «микрокластера» и трайб поверх, однако отказались от трайба и самостоятельно группируем результаты ибо запросы простые.

    Крайне ограниченная возможность поменять маппинг. Причем даже простое добавление поля приводит к необходимости переиндексировать данные (но это правда на ЕS 1.7, в свежих не знаю)


    1. CyberSoft
      23.08.2018 14:51

      Тоже дошли до состояния тупящих нод, подумываем про разделение на кластеры, ситуация вроде позволяет.

      Кстати, про холодные индексы: пилил их для внутреннего использования, после попробовал предложить эту фичу девелоперам, но они отказались, слишком сложно. У нас на проде прилично экономит хип, но не никак не посмотрю, как сильно ухудшились поиски. Лежит здесь: github.com/m31collision/elasticsearch/tree/unloadable-indices


      1. FYR
        23.08.2018 15:30

        Видимо одинаковые мысли приходят. Мы запилили крайне похожую вещь для 1.7 аналогично девелоперы отказались (но мы с++, так что джава код там был наверное не очень).
        Идея полностью аналогичная + запросы к таким индексам идут через отдельный тредпул. Плюс держим некое количество загруженных «замороженных» индексов в кеше с неким подобим сегментированного LRU алгоритма вытеснения. С учетом того что активных данных у нас примерно 10/300 экономия была существенная.


    1. divanikus
      23.08.2018 14:57

      Скорость миграции можно поднять, есть опция, по дефолту насколько помню не более 20МБ/с. rsync правда действительно быстрее, но в версиях с 5.х геморней.


      1. adel-s Автор
        23.08.2018 14:59

        Вот это очень интересно. Не можете подсказать где эту опцию найти? Я все перерыл, не нашел.


        1. FYR
          23.08.2018 15:24

          Наверное имеется ввиду вот это:

          max_restore_bytes_per_sec

          Throttles per node restore rate. Defaults to 40mb per second.


          1. divanikus
            23.08.2018 16:03

            Нет, indices.store.throttle.max_bytes_per_sec, но 5-ке выпили похоже, не учел.


          1. divanikus
            23.08.2018 16:15

            Или вот это indices.recovery.max_bytes_per_sec. Сам уже точно не помню.

            И еще вот эту группу настроек можно посмотреть:
            cluster.routing.allocation.node_initial_primaries_recoveries
            cluster.routing.allocation.node_concurrent_incoming_recoveries
            cluster.routing.allocation.node_concurrent_outgoing_recoveries
            cluster.routing.allocation.node_concurrent_recoveries
            cluster.routing.allocation.cluster_concurrent_rebalance


  1. AnyKey80lvl
    23.08.2018 12:58

    PUT .kibana/_settings
    {
    «index»: {
    «number_of_replicas»: "<количество_дата_нод>"
    }
    }


    Наверное, правильно «количество_дата_нод — 1» — при трёх нодах заходтим один primary shard и две реплики.


    1. AnyKey80lvl
      23.08.2018 13:09

      Кстати, тут еще более полезный вариант discuss.elastic.co/t/index-auto-expand-replicas/6893


  1. sabio
    24.08.2018 00:15
    +1

    А ещё, если индексы не оптимизировать, можно запросто упереться в лимит количества файловых дескрипторов в ОС.


  1. AlexeyVi
    24.08.2018 10:15
    +2

    По поводу компрессии курсоров, проще в настройка Java выставить -XX:+UseCompressedOops, она просто не даст запуститься с объемом Heap когда компрессия отключается (будет ругаться).
    Дополнительно перфоманса можно выжать, если Java покрутить)
    Я на проде использую GC G1, Huge Pages (-XX:+UseLargePages) большие странички не свопятся, не подвержены фрагментации и все остальные плюхи.
    Желательно писать логи GC во время подручивания Java и анализировать их например через , чтоб оценить работу GC
    А так же, использовать jstatd и VusialVM для просмотра работы GC в режиме online.
    В ранних версия эластика и Java задавался объем young поколения (обычно 1 GB) через параметр -Xmn
    Столкнулся с таким кейсом, когда очень активно использовался young space эластиком, и так как объем был небольшой частый вызов GC. Увеличил в несколько раз наблюдая через VisualVM. Итог нет бешеного GC, эластик стал работать существенно быстрее.
    Для тех, кто юзает mmapfs через sysctl покрутить надо vm.min_free_kbytes для более раннего запуска дефрагментации памяти.


    1. vladimir_dolzhenko
      24.08.2018 10:35

      С GCG1 на ранних сборках 8ки (и кажется даже 10ки) наблюдали забавные глюки — собственно поэтому официально этот сборщик не поддерживается, но в планах его включить т.к. CMS уже помечен как deprecated в 10ке, и Oracle/OpenJDK настоятельно рекомендуют именно G1.


      1. AlexeyVi
        24.08.2018 10:59

        Расскажите, я не встречал не на 8-ке, не на 9-ке и на 10-ке тем более. С 10 версии Java G1GC по умолчанию идет.


        1. vladimir_dolzhenko
          24.08.2018 11:15

          В старом посте упоминаются A Heap of Trouble: G1:

          LUCENE-6098: Indexwriter changecount assertion fail with g1gc и целый список от Lucene:

          Do not, under any circumstances, run Lucene with the G1 garbage collector. Lucene's test suite fails with the G1 garbage collector on a regular basis, including bugs that cause index corruption.


          Учитывая то, что баг ( bugs.openjdk.java.net/browse/JDK-8038348 ) на который ругаются таки закрыли — сейчас идёт long run test на G1 и если новых проблем не будет — то партия даст добро.


        1. Ruslan_Y
          24.08.2018 12:32

          У нас, при высокой нагрузке по индексации, периодически одна из дата-нод получала очень высокую нагрузку и уходила в себя, остальной кластер простаивал и ждал пока она разгрузится. Грешили на железо, но проблема была плавающая (проблемная дата нода проявлялась случайно) и на низкой нагрузке не проявлялась. В итоге помог возврат с G1 на CMS. Если ничего не путаю, это был ES2.х и JavaSE 8u25.


          1. AlexeyVi
            24.08.2018 12:45

            Не разу таких ситуаций не было с G1GC.
            У меня есть один ES 2.x работает на 8 Java (оракловая jdk-8u172-linux-x64.rpm)
            Никаких проблем. А вы не пробовали через jstatd посмотреть, что происходит в Heap.
            Собрать логи GC, проанализировать их в gceasy.io, очень хорошо показывает проблемы. Вопрос номер два, не наблюдался большой systime, что может быть указателем на большую фрагментацию памяти.