Чтобы понять, как работает репликация в Elasticsearch, вы уже должны понимать, как работает шардинг, поэтому сначала обязательно ознакомьтесь с этим.
Аппаратное обеспечение может выйти из строя в любой момент, а в программном обеспечении иногда бывают ошибки. Давайте посмотрим правде в глаза, иногда вещи просто перестают работать. Чем больше аппаратная емкость, тем выше риск, что какое-то оборудование перестанет работать, например, сломается жесткий диск. Принимая это во внимание, вероятно, целесообразно иметь какой-то механизм отказоустойчивости и обхода отказа. Именно здесь на помощь приходит репликация.
Elasticsearch изначально поддерживает репликацию ваших шардов, что означает, что шарды копируются. Когда шард реплицируется, его называют либо репликой шарда, либо просто репликой, если вам лень. Осколки, которые были реплицированы, называются первичными. Первичный шард и его реплики называются группой репликации. Не стоит слишком беспокоиться об этой терминологии.
Пример, который вы видите выше, основан на примере из введения в архитектуру Elasticsearch с индексом объемом один терабайт, разделенным на четыре шарда по 256 гигабайт каждый. Осколки теперь являются первичными, и каждый из них имеет реплику.
Репликация служит двум целям, главная из которых - обеспечение высокой доступности в случае отказа узлов или шардов. Для того чтобы репликация была эффективной, если что-то пойдет не так, шары-реплики никогда не выделяются на те же узлы, что и первичные шары, что также видно на приведенной выше диаграмме. Это означает, что даже если весь узел выйдет из строя, у вас будет как минимум одна реплика любого первичного шарда на этом узле. Другой целью репликации - или, возможно, побочным преимуществом - является повышение производительности поисковых запросов. Это происходит потому, что поиск может выполняться на всех репликах параллельно, что означает, что реплики фактически являются частью поисковых возможностей кластера. Поэтому реплики используются не только для обеспечения доступности, хотя это часто является основной мотивацией для использования репликации.
Как и в случае с шардами, количество реплик задается при создании индекса. По умолчанию количество реплик равно одной, то есть по одной на каждый шард. Это означает, что по умолчанию кластер, состоящий из более чем одного узла, будет иметь 5 первичных шардов и 5 реплик, итого 10 шардов на индекс. Это создает полную копию ваших данных, поэтому на любом из узлов может произойти сбой диска без потери данных. Причина, по которой я сказал, что кластер должен иметь более одного узла, заключается в том, что реплики никогда не хранятся на том же узле, что и основной шард, копией которого он является, как я уже говорил.
Подводя итог, можно сказать, что реплика шарда или реплика - это копия шарда. Шард с репликой называется первичным шардом, а первичный шард и его реплики - группой репликации. Цель репликации заключается как в обеспечении высокой доступности, так и в повышении производительности поисковых запросов, хотя основной целью часто является повышение отказоустойчивости. Это достигается тем, что репликационный шард никогда не хранится на том же узле, что и его основной шард. По умолчанию каждый шард в индексе имеет одну реплику, если кластер содержит более одного узла.
Поддержание синхронизации шардов реплик
Итак, теперь, когда вы знаете, что такое репликация и несколько подробностей о ней, как она работает на самом деле? Если, например, шард реплицируется пять раз, как обновляются реплики при изменении или удалении данных? Очевидно, что реплики должны быть синхронизированы, поскольку в противном случае мы столкнемся с проблемой, если документ будет удален из одной реплики, а из другой нет; в этом случае запросы будут непредсказуемыми, поскольку результат будет зависеть от того, из какой именно реплики происходит чтение.
Как же Elasticsearch синхронизирует все данные? Elasticsearch использует модель под названием primary-backup для репликации данных. Это означает, что первичный шард в группе репликации действует как точка входа для операций индексирования. В переводе на обычный английский это означает, что все операции, влияющие на индекс - такие как добавление, обновление или удаление документов - отправляются на первичный шард. Затем первичный шард отвечает за проверку операций и убеждается, что все в порядке. Это включает в себя проверку того, не является ли запрос структурно некорректным, например, попытка добавить число в поле объекта или что-то подобное. Если операция была принята первичным шардом, операция будет выполняться локально на самом первичном шарде. Когда операция завершится, она будет передана на каждый из реплик в группе реплик. Если у шарда есть несколько реплик, операция будет выполняться параллельно на каждой из них. Когда операция успешно завершится на каждой реплике и поступит ответ на основной шард, основной шард ответит клиенту, что операция завершилась успешно. Все это показано на следующей диаграмме.
Давайте повторим это еще раз, рассмотрев простой пример, основанный на приведенной выше диаграмме. У нас есть кластер с двумя узлами. У нас есть только один индекс, состоящий из двух шардов, каждый из которых имеет две копии. У нас есть клиент с левой стороны, который обычно является сервером, взаимодействующим с кластером. В данном случае мы хотим удалить документ из индекса. В этот момент Elasticsearch должен найти правильную группу репликации, а значит, и первичный шард. Это делается с помощью так называемой маршрутизации, в которую мы сейчас не будем вдаваться, поэтому можете считать это "черным ящиком". Просто знайте, что там что-то происходит, что находит соответствующую группу репликации и ее первичный шард - шард A в данном примере. Затем операция направляется на первичный шард, где она проверяется, а затем выполняется. После завершения операции на первичном хранилище операция отправляется на копирующие хранилища в группе репликации. В данном случае это означает, что операция удаления отправляется на реплики A1 и A2. Когда операция успешно завершается на обеих репликах, первичный шард, то есть шард A, подтверждает клиенту, что запрос был успешным.
В этом примере предполагается, что для шардов существует хотя бы одна реплика. Если реплик нет, операция просто выполняется непосредственно на шарде, и все.