Установки ElasticSearch для большого кластера с тяжелыми скоплениями

Контекстное и текущее состояние

Мы переносим наш кластер из Cassandra в полный кластер ElasticSearch. Мы индексируем документы в среднем ~ 250-300 док в секунду. В ElasticSearch 1.2.0 он представляет ~ 8Go в день.

{
 "generic":
    {
      "id": "twi471943355505459200",
      "type": "twitter",
      "title": "RT @YukBerhijabb: The Life is Choice - https://m.facebook.com/story.php?story_fbid=637864496306297&id=100002482564531&refid=17",
      "content": "RT @YukBerhijabb: The Life is Choice - https://m.facebook.com/story.php?story_fbid=637864496306297&id=100002482564531&refid=17",
      "source": "<a href=\"https://twitter.com/download/android\" rel=\"nofollow\">Twitter for  Android</a>",
      "geo": null,
      "link": "http://twitter.com/rosi_sifah/status/471943355505459200",
      "lang": "en",
      "created_at": 1401355038000,
      "author": {
        "username": "rosi_sifah",
        "name": "Rosifah",
        "id": 537798506,
        "avatar": "http://pbs.twimg.com/profile_images/458917673456238592/Im22zoIV_normal.jpeg",
        "link": "http://twitter.com/rosi_sifah"
      }
    },
 "twitter": {
   // a tweet JSON
 }
}

Наши пользователи сохраняют запросы в нашей базе данных SQL, и когда они запрашивают свою панель мониторинга, мы хотели бы запросить наш ES-кластер с их запросом (извлеченным из базы данных) и сделать некоторую агрегацию поверх него, используя новая структура агрегации ES.

Каждая панель мониторинга отображается с явным, выбранным пользователем диапазоном дат, поэтому мы всегда используем

"range": {
 "generic.created_at": {
   "from": 1401000000000,
   "to": 1401029019706
  }
}

вместе с запросом ES.

Мы указали _routing следующим образом:

"_routing":{
 "required":true,
 "path":"generic.id"
},

и _id:

"_id": {
  "index": "not_analyzed",
  "store": "false",
  "path": "generic.id"
}

В течение примерно 5 дней мы хранили 67 миллионов документов (около 40Go) внутри одного индекса. Мы узнали о хорошей практике разделения индекса на день. Итак, теперь наши индексы разделены днем ​​([имя-индекс] - [ГГГГ-ММ-ДД]).

В настоящее время каждый индекс имеет 5 осколков и 1 реплику, у нас есть кластер, состоящий из 3 машин с 8 ядрами, 16 ГБ оперативной памяти и 8-дюймовым жестким диском. Мы планируем использовать другую машину в качестве шлюза (8 ядер, 16Go RAM, 1To HDD).

Мы установили конфигурацию ES по умолчанию, кроме конфигурации кластера.

Вопросы

  • Для каждого документа, который мы хотим индексировать, мы говорим явно, какой индекс использовать. В настоящее время мы используем дату дня. Должна ли мы использовать дату документ, чтобы предотвратить горячую точку? Потому что в настоящее время означает, что документы из разных дней (указанные в их created_at) может жить в том же индексе текущего дня.
  • Достаточно ли 5 ​​осколков (или слишком много) для 21 600 000 документов днем?
  • Если мы хотим, чтобы все наши агрегированные запросы обрабатывались менее чем за 1 секунду, сколько реплик мы должны настроить?
  • Должны ли мы изменить нашу маршрутизацию? Поскольку мы не знаем заранее, какие документы будут обработаны до агрегации для каждого запроса, который мы делаем в кластере (поскольку запрос определяется пользователем)
  • Какое аппаратное обеспечение (сколько машин, какая конфигурация) мы должны помещать внутри этого кластера для поддержки 6 месяцев документов?

[Обновление]

Вот пример запросов:

Облако слов

GET idx-2014-05-01/stream/_search?search_type=count
{
 "query":{
   "bool": {
     "must": [{
       "query_string" : {
         "query" : "(generic.lang:fr OR generic.lang:en) AND (generic.content:javascript)"
        }},{
        "range": {
          "generic.created_at": {
            "from": 1401000000000,
            "to": 1401029019706
          }
        }}
     ]
   }
 },
  "aggs":{
    "words":{
      "terms":{
        "field": "generic.content",
        "size": 40
      }
    }
  }
}

Гистограмма

GET idx-2014-05-01/stream/_search?search_type=count
{
 "query":{
   "bool": {
     "must": [{
       "query_string" : {
         "query" : "generic.content:apple"
        }},{
        "range": {
          "generic.created_at": {
            "from": 1401000000000,
            "to": 1401029019706
          }
        }}
     ]
   }
 },
  "aggs":{
    "volume":{
      "date_histogram":{
        "field": "generic.created_at",
        "interval":"minute"
      }
    }
  }
}

Должен использоваться язык

GET idx-2014-05-01/stream/_search?search_type=count
{
 "query":{
   "bool": {
     "must": [{
       "query_string" : {
         "query" : "(generic.lang:fr OR generic.lang:en) AND (generic.content:javascript)"
        }},{
        "range": {
          "generic.created_at": {
            "from": 1401000000000,
            "to": 1401029019706
          }
        }}
     ]
   }
 },
  "aggs":{
    "top_source":{
      "terms":{
        "field": "generic.lang"
      }
    }
  }
}

view?id=AAIAAAD-U-%0AYBJN9lpixm6nxrnAaHQY5DoZ0FcNQ&trk=nav_responsive_tab_profile

Ответы

Ответ 1

Позвольте мне предисловие ко всем моим ответам/комментариям советом, чтобы попытаться, насколько это возможно, проверить эти сценарии самостоятельно. Хотя Elasticsearch очень масштабируема, существует много компромиссов, которые сильно зависят от размера и типа документа, объема и объема запросов, аппаратного обеспечения и ОС. Хотя есть много неправильных ответов, редко бывает один правильный ответ.

Я основываю этот ответ на нескольких активных кластерах, у которых есть (в настоящее время) около полумиллиона активных документов в них, а также некоторые недавние бенчмаркинга, которые мы выполнили примерно в 4 раза по вашему объему (около 80 М документов, поступающих в день во время тест).

1) Во-первых, вы не создаете большую часть горячей точки с тремя узлами, когда у вас есть хотя бы один индекс с 5 осколками и 1 реплика на каждый осколок. Elasticsearch отделяет каждую реплику от нее первичной до другой node, и в целом попытается сбалансировать нагрузку осколков. Elasticsearch по умолчанию будет хэш на идентификаторе, чтобы выбрать осколок для индексации (который затем копируется на реплику). Даже при маршрутизации у вас будет только проблема с горячими точками, если у вас есть одиночные идентификаторы, которые создают большое количество документов в день (это диапазон вашего индекса). Даже тогда это не будет проблемой, если эти идентификаторы не будут давать значительного процента от общего объема, и их так мало, что вы могли бы сжиматься только на 1 или 2 черепа.

Только вы можете определить, что на основе ваших шаблонов использования - я бы предложил как некоторый анализ вашего существующего набора данных искать слишком большие концентрации, так и анализ ваших вероятных запросов.

Больший вопрос у меня есть характер ваших запросов. Вы не показываете полный запрос или полную схему (я вижу, что "generic.id" ссылается, но не в схеме документа, и ваш запрос показывает, как вытягивать каждый документ за временной интервал - это правильно?). Пользовательская маршрутизация для индексации наиболее полезна, когда ваши запросы привязаны точным соответствием в поле, используемом для маршрутизации. Таким образом, если бы у меня был индекс со всеми документами в нем, и мой шаблон запроса состоял в том, чтобы извлекать только один пользовательский документ в одном запросе, то пользовательская маршрутизация по идентификатору пользователя была бы очень полезна для повышения производительности запросов и снижения общей нагрузки кластера.

Вторая вещь, которую следует учитывать, - это общий баланс проглатывания против запросов. Вы глотаете более 20 миллионов документов в день - сколько запросов вы выполняете в день? Если это число < < < скорость проглатывания, которую вы, возможно, захотите подумать, в соответствии с потребностью в специальном маршруте. Кроме того, если производительность запросов хороша или велика, вы можете не захотеть добавить дополнительную сложность.

Наконец, индексирование по дате проглатывания против created_at. Мы тоже боролись с этим, так как у нас есть некоторое отставание в получении новых документов. На данный момент мы отправились с хранением по дате приема, поскольку это проще в управлении, а не большой проблемой для запроса нескольких индексов за раз, особенно если вы автоматически создаете псевдонимы на 1 неделю, 2 недели, 1 месяц, 2 месяца и т.д. Большая проблема заключается в том, что такое дистрибутив: если у вас есть документы, которые появляются через несколько месяцев или месяцев, возможно, вы захотите перейти на индексирование с помощью create_at, но это потребует постоянного хранения этих индексов в Интернете в течение некоторого времени.

В настоящее время мы используем несколько индексов документов в день, в основном формат "-". Практически это в настоящее время означает 5 индексов в день. Это позволяет нам быть более избирательным относительно перемещения данных в кластер и из него. Не рекомендация для вас, просто то, что мы узнали, полезно для нас.

2) Здесь большое мнение о ES - с созданием нового индекса каждый день вы можете корректировать с течением времени, чтобы увеличить количество осколков на индекс. Хотя вы не можете изменить его для существующего индекса, вы каждый день создаете новый, и вы можете основывать свое решение на реальной аналитике производства. Вы, конечно, хотите посмотреть номер и быть готовым увеличить количество осколков, если/если вы принимаете внутрь в день. Это не самый простой компромисс - каждый из этих осколков является экземпляром Lucene, который потенциально имеет несколько файлов. Больше осколков на индекс не является бесплатным, поскольку это умножается на время. Учитывая ваш случай использования 6 месяцев, более 1800 осколков открываются через 3 узла (182 дня x 5 первичных и 5 реплик в день). Там, вероятно, открываются кратные файлы на каждый осколок. Мы обнаружили некоторый уровень накладных расходов и влияние на использование ресурсов на наших узлах, так как общее количество осколков увеличилось в кластере в этих диапазонах. Ваш пробег может быть разным, но я был бы осторожен в увеличении количества осколков на индекс, когда вы планируете хранить 182 индекса (6 месяцев) за раз - это довольно множитель. Я бы определенно оценил это раньше времени, если вы внесете какие-либо изменения в счетчик осколков по умолчанию.

3) Ни в коем случае никто не может предсказать производительность запроса раньше времени. Он основан на общей загрузке кластера, сложности запросов, частоте запросов, оборудовании и т.д. Он очень специфичен для вашей среды. Вам нужно будет сравнить это. Лично учитывая, что вы уже загрузили данные, я бы использовал снимок ES и восстановил, чтобы довести эти данные в тестовой среде. Попробуйте по умолчанию с 1 репликой и посмотрите, как это происходит. Добавление черепов реплик отлично подходит для избыточности данных и может помочь распространять запросы по кластеру, но оно стоит довольно крутой ценой - 50% -ное увеличение объема хранения, а каждый дополнительный реплика-осколок приведет к дополнительным расходам на прием в node, на котором он работает. Это здорово, если вам нужна избыточность и вы можете избавиться от емкости, не так велика, если вам не хватает достаточного объема запросов, чтобы действительно воспользоваться ею.

4). Ваш вопрос неполный (он заканчивается на "мы никогда" ), поэтому я не могу ответить на него напрямую - однако более важный вопрос - почему вы настраиваете маршрутизацию для начала? Уверен, что он может иметь большие преимущества в производительности, но это полезно только в том случае, если вы можете сегментировать набор документов в поле, которое вы используете для маршрутизации. Это не совсем понятно из вашего примера данных и частичного запроса, если это случай. Лично я бы тестировал его без какой-либо пользовательской маршрутизации, а затем попробовал то же самое с ним и посмотрел, оказывает ли оно существенное влияние.

5) Еще один вопрос, который потребует некоторой работы с вашей стороны. Вам необходимо отслеживать (как минимум) использование кучи JVM, общую память и использование процессора, использование диска и активность диска io с течением времени. Мы делаем это с пороговыми значениями, установленными для предупреждения, прежде чем рассматривать проблемы, чтобы мы могли добавить новых членов в кластер раньше. Имейте в виду, что при добавлении node в кластер ES будет пытаться перебалансировать кластер. Запуск производства только с тремя узлами с большим набором исходных документов может вызвать проблемы, если вы потеряете проблемы node (выпадение кучи, ошибка JVM, отказ оборудования, сбой сети и т.д.). ES собирается пойти Желтым и остаться там в течение некоторого времени, пока он перетасовывается.

Лично для больших номеров документов и высокого уровня приема я бы начал добавлять узлы раньше. С большим количеством узлов на месте это меньше проблем, если вы берете node для обслуживания. Что касается вашей существующей конфигурации, как вы дошли до 8 ТБ жесткого диска на node? Принимая во внимание 8 ГБ в день, который кажется излишним в течение 6 месяцев данных. Я сильно подозреваю, учитывая объем данных и количество индексов/осколков, которые вы хотите переместить на большее количество узлов, что еще больше уменьшит ваше хранилище по требованию node.

Я бы определенно хотел сравнить максимальный объем документов на node путем циклического переполнения большого объема и циклов нормальной частоты запросов в кластере с одним или двумя узлами и увидеть, где он не работает (либо в производительности, высыпание кучи или другая проблема). Затем я планировал сохранить количество документов на node значительно ниже этого числа.

Все, что сказал, что я выйду на конечность и скажу, что сомневаюсь, что вы будете довольны 4 миллиардами плюс документы на 3 16-гигабайтных узлах. Даже если он сработает (опять же, тест, тест, тест), потерявший один node, станет действительно большим событием. Лично мне нравятся меньшие узлы, но предпочитаю их много.

Другие мысли - мы первоначально сравнивали по 3 экземплярам Amazon EC2 m1.xlarge(4 ядра, 15 ГБ памяти), которые отлично работали в течение нескольких дней после приема на 80-миллиметровые документы в день, что больше среднего размера документа, чем кажется. Самая большая проблема заключалась в том, что количество индексов и осколков открылось (мы создавали пару сотен новых индексов в день, возможно, на пару тысяч больше очков в день, и это создавало проблемы). С тех пор мы добавили несколько новых узлов, которые имеют 30 ГБ памяти и 8 ядер, а затем добавили еще 80 миллионов документов для его проверки. Наш нынешний подход к производству заключается в том, чтобы сохранить предпочтение более умеренным размерам узлов, а не нескольким крупным.

UPDATE:

Что касается оборудования для бенчмаркинга, то, как указано выше, сравнивается с 3 виртуальными экземплярами Amazon EC2 m1.xlarge, работающими с ubuntu 12.04 LTS и ES 1.1.0. Мы работали около 80 миллионов документов в день (извлекаем данные из базы данных MongoDB, которую мы ранее использовали). Каждый экземпляр имел 1 ТБ хранилища через Amazon EBS, с предоставлением IOPS, по моему мнению, 1000 IOPS. Мы бегали около 4-5 дней. Похоже, что мы немного ограничивали процессор на 80 М в день и считаем, что больше узлов увеличило бы скорость приема. По мере того как эталонный тест и число индексов и осколков увеличилось, мы увидели увеличение давления памяти. Мы создали большое количество индексов и осколков (примерно 4-5 индексов на 1 М документов или около 400 индексов в день, с 5 основными осколками и 1 черепом реплик на индекс).

Что касается псевдонимов индексов, мы создаем с помощью псевдонимов с индексацией cron для 1 недели назад, 2 недели назад и т.д., чтобы наше приложение могло просто нажать известный псевдоним индекса и всегда работать с заданным временным интервалом с Cегодня. Мы используем aliases rest api для создания и удаления их:

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html