1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/didiopensource-LogiEM

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
LogiEM最佳实践.md 29 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 06.03.2025 02:38 aaceedf

Команда LogiEM, используя внутренний опыт компании Didi в использовании Elasticsearch (ES), сформулировала несколько лучших практик использования ES и платформы LogiEM. Основной акцент сделан на создание индексов, установление маппингов, оптимизации запросов и записи данных.

1. Создание индексов

На данный момент рекомендовано использовать шаблоны индексов, основанные на времени для разделения данных, обычно это деление по дням, месяцам или годам. Индексы, запрошенные пользователями, являются логическими индексами, а фактические хранимые индексы — физическими.

Например, если имя шаблона индекса при регистрации пользователя равно "abc", и выбрано хранение по месяцам, то фактические хранимые индексы будут иметь вид "abc_201812" и "abc_201901".

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

1.1 Запрещено использование индексов со своими собственными суффиксамиПри записи документов в Elasticsearch, если указанный индекс ещё не создан в кластере, он будет создан автоматически во время записи. Если каждый раз использовать новый индекс, это приведёт к частому созданию новых индексов, что может вызвать увеличение метаданных кластера, высокий расход памяти, замедление восстановления и другие проблемы. Частое создание индексов также может заблокировать узел-master, что влияет на стабильность и производительность системы.## 1.2 Запрещено создание долгосрочных индексов по дням

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

1.3 Недопустимо отсутствие разделения индексов

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

2. Установка маппингов

2.1 Запрещено полное очистное преобразование сообщений в сценариях журналирования

В сценариях журналирования сообщение используется для хранения оригинального журнала. В стандартных сценариях KV формата сообщения можно выполнять специализированное очистное преобразование для конкретных полей, таких как traceId и actionName.Запрещено выполнять полное очистное преобразование сообщений без указания конкретных полей для очистки. Полное очистное преобразование может привести к увеличению размера маппинга, что затрудняет поиск и негативно влияет на производительность и стабильность системы.## 2.2 Недопустимо выполнение словесного анализа сообщений в сценариях журналирования

Логическая сцена использует поле message для хранения исходного текста логов; обычно поиск в поле message в Elasticsearch (ES) не выполняется, даже если это нестандартный формат ключ-значение. Очистка поля message или выполнение по нему поиска не рекомендуются.

Поле message может быть очень длинным, содержание также не всегда постоянное, поэтому выполнение поиска по этому полю требует значительного количества хранилища.

Для такой ситуации рекомендуется при формировании логов следовать внутренним правилам компании Didi, а затем выполнять поиск по необходимым полям после очистки данных.

2.3 Не рекомендуется произвольно увеличивать количество полей в маппинге

Свойство free schema Elasticsearch позволяет пользователям динамически менять маппинг, записывая данные в формате JSON. Однако, если свойства JSON постоянно меняются и увеличиваются, это приведёт к тому, что количество полей в маппинге будет расти.

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

2.4 Рекомендуется выполнять анализаторы по необходимостиДля данных, записанных в Elasticsearch, рекомендуется использовать анализаторы по конкретной необходимости полей. Для полей, которые не требуют анализа, следует отключить его в маппинге, установив значение "index" как no. Это позволит существенно сэкономить ресурсы.## 2.5 Рекомендуется выполнять агрегацию по необходимости

Для данных, записанных в Elasticsearch, рекомендуется выполнять агрегацию по конкретной необходимости полей. Для полей, которые не требуют агрегации, следует отключить её в маппинге, установив значение "doc_values" как false. Это позволит существенно сэкономить ресурсы.

2.6 Выбор типа индекса для полей со значениями

Elasticsearch автоматически выбирает тип индекса на основе содержимого поля. Например, status=1 автоматически преобразуется в long тип, name="es" — в keyword тип.

Различные типы индексов используют различные структуры данных. Числовой тип long, integer использует BKD как основную структуру данных, подходящую для запросов диапазона, но не для точных запросов key=value. Точное число сравнений числовых полей потребует значительного использования процессора для создания битсета. Keyword тип использует FST и SkipList как основную структуру данных, подходящую для точных запросов key=value, где идентификаторы документов, удовлетворяющие условиям, уже хранятся в обратном индексе, и нет необходимости в реальном времени создавать битсет.

Особое внимание: для полей базы данных MySQL, предназначенных для хранения перечисляемых значений, таких как поле status, xxx_type, следует использовать keyword как тип индекса Elasticsearch, а не long тип.Запросы можно сначала рассмотреть в рекомендациях по оптимизации запросов от официального сайта ElasticSearch: https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-search-speed.html

3.1 Недопустимость использования звездочки (*)

При поиске в Elasticsearch поддерживаются префиксы со звездочками (), такие как abc, что будет соответствовать всем индексам, начинающимся с abc, таким как abc_201501 до abc_201901. Добавление сложных условий поиска приведёт к полному сканированию таблицы, что может легко вызвать проблемы с работой Elasticsearch.

Поэтому использование звездочек (*) в запросах не рекомендуется. Прямое использование * запрещено в шлюзе LogiEM. Вместо этого следует использовать реальные названия индексов при выполнении запросов, например: SELECT * FROM abc_201901; SELECT * FROM abc_201901, abc_201902;

3.2 Недопустимость сложных агрегирующих запросов

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

Шлюз LogiEM и более новые версии Elasticsearch следят за использованием памяти при выполнении агрегирующих запросов. Если расход памяти становится слишком большим, запрос будет заблокирован.Используйте агрегирующие запросы (aggs) осторожно, особенно если они используют ключевые слова cardinality и script, так как они могут существенно увеличивать нагрузку на память и вызывать проблемы производительности.

3.3 Избегайте запросов, возвращающих большое количество данных

Каждый запрос Elasticsearch возвращает все совпадающие данные, что может привести к необходимости просмотра всех совпадающих записей. Это может привести к замедлению общего времени выполнения запроса.

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

3.4 Рекомендуется использовать поля маршрутизации в условиях запроса

При записи документов в Elasticsearch можно указать поле маршрутизации (routing field). Указание этого поля в условиях запроса может повысить скорость выполнения запроса. Пример: Поле abc.id может быть использовано как поле маршрутизации для индекса abc. В условиях запроса можно указать abc.id, например: SELECT * FROM abc_201901 WHERE abc.id = 123 AND abc.passenger_id = 123 GROUP BY abc.driver_id;Elasticsearch использует указанное поле маршрутизации для быстрого нахождения конкретного раздела (shard) и последующего выполнения фильтрации и агрегации только внутри этого раздела, что позволяет избежать полного прохода через все разделы индекса и повышает эффективность выполнения запроса. ## 3.5 Не рекомендуется выполнять сложные запросы на больших индексахСуществуют индексы с очень большим объёмом данных, превышающим миллиарды записей. При выполнении запросов на таких индексах следует обратить особое внимание на сложность запросов. Когда условия фильтрации попадают в большое количество данных, запрос может выполняться очень медленно, даже превышая время ожидаемого завершения. Кроме того, такие индексы обычно имеют множество шардов, что требует значительных ресурсов для каждого запроса.

При работе с большими индексами обращайте внимание на оптимизацию запросов и выбор наиболее подходящего способа выполнения запроса. Основной принцип — это минимизация области поиска.

3.6 Рекомендации по использованию правильного метода сортировки

По умолчанию Elasticsearch сортирует данные по значению score, вычисляемому для каждой записи. Для пользователей, которым не требуется специальная сортировка, можно использовать внутренний порядок _doc, чтобы избежать этапа расчёта score. Однако при сортировке по другим полям производительность запроса снижается, так как каждая запись должна получить значение своего поля из DocValues, что может вызвать операции чтения/записи (IO) и замедлить выполнение запроса.

Пример DSL и SQL для сортировки по _doc:

DSL:

"sort": [
  {
    "_doc": {
      "order": "asc"
    }
  }
]

SQL: ORDER BY _doc## 3.7 Внимание при использовании ключевого слова post_filter

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

Дополнительная информация о post_filter доступна по адресу: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-post-filter.html

3.8 Настройка параметров времени ожидания (timeout)

  1. Параметр timeout в запросах Elasticsearch применяется к отдельному шарду. Если запрос одного шарда превышает указанное время ожидания, он немедленно прекращает выполнение и возвращает частичный результат. Это может привести к тому, что результат будет неполным. В ответе на запрос поле timed_out указывает, был ли запрос прерван из-за превышения времени ожидания. Значение false означает, что запрос завершился успешно, без прерываний. Значение true указывает на то, что запрос был прерван из-за превышения времени ожидания, и пользователь должен проверить целостность полученного результата. Например, если timed_out=false, это значит, что запрос завершился без прерываний.```json { "took": 9, "timed_out": false, "_shards": { "total": 12, "successful": 12, "failed": 0 }, "hits": { ... } }
По умолчанию значение `timeout` в Elasticsearch обычно составляет 5-10 секунд. При выполнении массовых запросов может возникнуть превышение времени ожидания (`timeout`). Пользователи могут указывать значение `timeout` в параметрах запроса, подробнее см.: <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html>. Интерфейсы SQL также поддерживают установку значения `timeout`.2\. В шлюзе LogiEM (Gateway) можно настроить параметр `socket_timeout`, который представляет время ожидания ответа от ES. Если время ожидания превышено, клиент получает сообщение о превышении времени ожидания (`timeout`). Конкретное имя параметра `socket_timeout` имеет максимальное значение 120 секунд.

3\. Клиенты могут самостоятельно настраивать параметр `timeout`, используя SDK различных языков программирования. Этот параметр применяется только к клиентской части, но не влияет на время ожидания в шлюзе Gateway и внутреннем окружении ES. Поэтому при настройке `timeout` следует проявлять осторожность. Рекомендовано устанавливать `timeout` в зависимости от сложности запроса.

## 3.9 Оценка полноты результатов поиска

Результаты поиска в ES выглядят следующим образом:

```json
{
  "took": 9,
  "timed_out": false,
  "_shards": {
    "total": 12,
    "successful": 12,
    "failed": 0
  },
  "hits": {
    ...
  }
}

Чтобы убедиться, что результаты поиска корректны, помимо получения вышеописанной информации, необходимо проверить следующие два аспекта: 1. Убедитесь, что timed_out равно false. Подробное описание параметра timed_out см. в разделе: 3.8 Настройка параметров timeout. 2. Убедитесь, что failed в _shards равно 0. Если это число больше нуля, значит часть shards запроса завершилась с ошибками. В этом случае будет предоставлена информация об этих ошибках.

3.10 Советы по использованию terms-запросовРекомендуется использовать следующую структуру terms-запроса, где количество значений Value должно быть менее 100.

3.11 Советы по использованию wildcard-запросов

1. Ограничение длины строки запроса Рекомендуется ограничивать длину строки запроса до 20 символов.

2. Исключение использования * в начале строки запроса Использование * в начале строки запроса заставляет Elasticsearch выполнять полное сканирование всех индексов, что крайне невыгодно с точки зрения производительности и расхода ресурсов. Рекомендуется избегать такого подхода.

3. Использование полнотекстового поиска вместо wildcard-запросов Elasticsearch поддерживает полнотекстовый поиск, который намного более эффективен, чем wildcard-запросы. Дополнительная информация о типах полнотекстового поиска доступна здесь: https://www.elastic.co/guide/en/elasticsearch/reference/current/text.html

3.12 Советы по использованию запросов со скроллингом (scroll)При использовании запросов со скроллингом (scroll) временные данные запроса (SearchContext) остаются занятыми памятью Elasticsearch до завершения скроллинга или до истечения времени ожидания. Поэтому рекомендуется не устанавливать слишком большие значения времени ожидания (более 5 минут). Рекомендуется использовать время ожидания около одной минуты или активно вызывать метод clear после завершения скроллинга для освобождения занятых ресурсов.

3.13 Предложения по точному совпадению типов полей

Для точного совпадения типов полей рекомендуется использовать тип keyword, а для диапазонных запросов — number (integer/long/double/float и т.д.).## 3.14 Лучше запретить сортировку по _id Сортировка по _id использует fielddata, что может легко привести к переполнению памяти. Поэтому сортировка по _id должна быть запрещена.

3.15 Запрет использования fielddata для полей типа text

Для полей типа text лучше не использовать fielddata, чтобы избежать переполнения памяти из-за слишком большого размера fielddata.

3.16 Разделение шардов

Указание конкретного разделённого шарда для запроса, настройка Routing, indexSort и ограничение количества попаданий в общие шарды

4. Оптимизация записи

Для оптимизации записи можно обратиться к руководству Elasticsearch по оптимизации скорости индексации: https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-indexing-speed.html

4.1 Использование bulk для записи

Рекомендуется использовать bulk для записи. Количество записей в одном bulk запросе должно быть разумным, зависящим от конфигурации сервера и размера документов. В качестве примера можно указать значение 1000 или до 2МБ.

4.2 Многопоточная запись

Многопоточность может повысить производительность записи, но количество потоков не должно быть чрезмерным.

4.3 Штрихкодировка записи

Данные внутри одного bulk запроса должны быть распределены по одному шарду, чтобы избежать эффекта длинного хвоста и обеспечить высокую производительность записи.## 4.4 Уникальный идентификатор Если уникальный идентификатор не требуется, его следует не указывать при записи, позволяя Elasticsearch генерировать его автоматически. Это позволяет избежать проверки версий и идентификаторов, повышая производительность.

4.5 Translog

В экстренных случаях, таких как отключение питания, когда допустимо потерять некоторые данные, рекомендуется установить режим записи translog в асинхронном режиме.

4.6 Время обновления и буфер записи

Время обновления и буфер записи могут быть увеличены для улучшения производительности.

4.7 Настройка схемы маппинга

В маппингах поля, которые не требуют индексации или сортировки, следует удалить свойства index и doc_values для повышения производительности записи.

5. Оптимизация архитектуры развертывания

  1. SSD накопители

  2. Изоляция ролей master, client и data node

  3. По спецификации оборудования возможно использование одного экземпляра на одной машине, нескольких экземпляров на одной машине или нескольких кластеров на одной машине

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/didiopensource-LogiEM.git
git@api.gitlife.ru:oschina-mirror/didiopensource-LogiEM.git
oschina-mirror
didiopensource-LogiEM
didiopensource-LogiEM
master