Статьи

Как сделать запрос InfluxDB

InfluxDB — это популярная база данных временных рядов, и я здесь, чтобы показать вам, как ее запрашивать. Он использует SQL-подобный (или, если честно, «почти-SQL») язык.

1
SELECT * FROM "foodships" WHERE time > now() - 1h

Этот язык работает и поддерживается в InfluxDB с первого дня, и у него есть как плюсы, так и минусы:

  1. Новым пользователям легко взаимодействовать с базой данных на языке, который они уже знают. SQL популярен, и многие разработчики уже знают его. Этот синтаксис запросов помог InfluxDB расти в первые дни.
  2. Как я уже говорил, InfluxQL — это язык «amost-SQL». Написание языка SQL-запросов не простая работа. Одна из проблем заключается в том, что администраторы баз данных имеют некоторые ожидания от SQL, но наш язык не полностью совместим с SQL. Это создает много несоответствий и сомнений .
  3. Одной из характеристик базы данных временных рядов является то, что запись не может блокировать чтение, а чтение не может блокировать запись. Это необходимая вещь. Ваши устройства IOT или ваши серверы всегда будут записывать метрики, а ваша панель мониторинга, аналитические инструменты и менеджеры предупреждений будут считывать данные из базы данных. InfluxDB нужно что-то более масштабируемое.
  4. На данный момент механизм хранения и язык запросов находятся в одном проекте, который блокирует быструю итерацию кода, который мы хотели бы иметь. Язык запросов развивается намного быстрее по сравнению с механизмом хранения. Движок нуждается в стабильности, но язык запросов нуждается в большем количестве функций и возможностей.
  5. InfluxQL нуждается в ре-архитектуре, потому что команда не смогла реализовать все удивительные идеи, требуемые сообществом.
  6. В настоящее время SQL очень прост в изучении, но в нашем стеке есть еще один DSL-доступ: скрипт TICK, используемый Kapacitor для отправки предупреждений и уменьшения количества ваших серий.
  7. InfluxQL не имеет математических функций, потому что язык не позволяет нам добавлять их простым способом. С IFQL их будет очень легко реализовать.

Во время InfluxDays в Сан-Франциско Пол Дикс , технический директор и основатель InfluxData, выпустил на сцену новый язык запросов с открытым исходным кодом, чтобы приблизить анализ данных к InfluxDB. Это называется IFQL .

Архитектура

1
2
3
4
5
6
7
8
var cpu = select(db: "telegraf")
  .filter(exp:{"_measurement" == "cpu" and "_field" == "usage_user"})
  .range(start: -30m)
   
select(db: "telegraf")
  .filter(exp:{"_measurement" == "mem" and "_field" == "used_percent"})
  .range(start: -30m)
  .join(on:["host"], eval:{$ + cpu})

IFQL — это не просто язык запросов. У него есть синтаксический анализатор, который читает запрос, подобный приведенному выше, и генерирует план, который можно визуализировать как JSON и запускать напрямую через IFQL. Это означает, что синтаксис, который вы видите, является лишь одной из возможных реализаций. Настоящий контракт заключается между планом и обработчиком.

Архитектура и идея проекта позволят нам переопределить InfluxQL и PromQL, TICK Script поверх IFQL AST. Кроме того, если у вас есть построитель запросов или вам необходимо создать собственную реализацию для взаимодействия с InfluxDB, вы можете сгенерировать план в виде простого JSON и передать его в IFQL. Гибкая и удивительная.

IFQL предназначен для расширения и достижения этой цели — мы извлекли важный урок из Telegraf. Вам нужен чистый интерфейс и единственная точка входа, чтобы разработчики с удовольствием внесли свой вклад в ваш проект. Вот почему у IFQL есть каталог /functions . Он содержит все функции, поддерживаемые в настоящее время, и участники, желающие добавить функции, должны работать только в этом каталоге.

TICK Script и IFQL

Одна из целей IFQL — предоставить все возможности, которые в настоящее время предоставляет TICK Script, чтобы мы могли запрашивать, обрабатывать и отправлять оповещения, не изучая два языка.

В настоящее время у нас есть функции, реплицированные в обоих проектах, но мы сможем повторно использовать их с IFQL.

На данный момент IFQL является отдельным проектом, доступным на GitHub . Помимо анализатора и планировщика, он предоставляет простой http-демон с именем ifqld для запуска некоторых тестов.

Он находится в бета-версии, что означает, что API и синтаксис запросов изменятся, но его очень легко настроить. Я буду использовать Docker для этого примера, но вы можете найти здесь исполняемые файлы IFQL, deb и rpm, если вы не знаете Docker.

Давайте загрузим файл конфигурации InfluxDB из репозитория IFQL:

1
2
3
wget https://raw.githubusercontent.com/influxdata/ifql/master/docker-compose.yml
mkdir examples
wget https://raw.githubusercontent.com/influxdata/ifql/master/examples/influxdb.conf -O examples/influxdb.conf

Основным отличием является параграф, который включает IFQL:

1
2
3
4
[ifql]
  enabled = true
  log-enabled = true
  bind-address = ":8082"

InfluxDB использует порт 8082 для запуска связи gRPC с IFQL.

1
docker-compose up

Как видите, мы создали сеть и развернули два контейнера. Одним из них является InfluxDB с нашей модифицированной конфигурацией и открытыми 8082 и 8086. Второй — IFQL v0.0.2. Он предоставляет порт 8093, и мы можем проверить, что все работает как положено, запустив простой curl:

1
2
3
4
5
6
15:21 $ curl -I http://localhost:8093/
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Tue, 28 Nov 2017 14:21:40 GMT
Content-Length: 19

Теперь давайте заполним нашу базу данных некоторыми примерами данных:

01
02
03
04
05
06
07
08
09
10
curl https://s3.amazonaws.com/noaa.water-database/NOAA_data.txt -o NOAA_data.txt
influx -import -path=NOAA_data.txt -precision=s -database=NOAA_water_database
influx
use NOAA_water_database
SELECT COUNT(*) FROM NOAA_water_database
> SELECT COUNT(*) FROM h2o_feet
name: h2o_feet
time count_level description count_water_level
---- ----------------------- -----------------
0    15258                   15258

Как видите, у нас есть несколько точек и измерений. Теперь мы будем взаимодействовать с ifqld используя curl чтобы запустить несколько основных примеров:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
20:11 $ curl -XPOST --data-urlencode 'q=from(db:"NOAA_water_database").filter(exp:{"_measurement"=="h2o_temperature"}).range(start: -500000h).limit(n: 10)' http://localhost:8093/query      
h2o_temperature,location=coyote_creek degrees=60 1439856000000000000                          
h2o_temperature,location=coyote_creek degrees=65 1439856360000000000                          
h2o_temperature,location=coyote_creek degrees=68 1439856720000000000                          
h2o_temperature,location=coyote_creek degrees=62 1439857080000000000                          
h2o_temperature,location=coyote_creek degrees=62 1439857440000000000                          
h2o_temperature,location=coyote_creek degrees=69 1439857800000000000                          
h2o_temperature,location=coyote_creek degrees=67 1439858160000000000                          
h2o_temperature,location=coyote_creek degrees=67 1439858520000000000                          
h2o_temperature,location=coyote_creek degrees=70 1439858880000000000                          
h2o_temperature,location=coyote_creek degrees=65 1439859240000000000                          
h2o_temperature,location=santa_monica degrees=70 1439856000000000000                          
h2o_temperature,location=santa_monica degrees=60 1439856360000000000                          
h2o_temperature,location=santa_monica degrees=62 1439856720000000000                          
h2o_temperature,location=santa_monica degrees=62 1439857080000000000                          
h2o_temperature,location=santa_monica degrees=60 1439857440000000000                          
h2o_temperature,location=santa_monica degrees=63 1439857800000000000                          
h2o_temperature,location=santa_monica degrees=64 1439858160000000000                          
h2o_temperature,location=santa_monica degrees=63 1439858520000000000                          
h2o_temperature,location=santa_monica degrees=63 1439858880000000000                          
h2o_temperature,location=santa_monica degrees=61 1439859240000000000

Давайте сравним ранжированный запрос from(db:"NOAA_water_database").filter(exp:{"_measurement"=="h2o_temperature"}).range(start:
-500000h).limit(n: 10)
from(db:"NOAA_water_database").filter(exp:{"_measurement"=="h2o_temperature"}).range(start:
-500000h).limit(n: 10)
from(db:"NOAA_water_database").filter(exp:{"_measurement"=="h2o_temperature"}).range(start:
-500000h).limit(n: 10)
с InfluxQL:

  • from работает немного похоже на select в SQL. Он выбирает database для запроса.
  • filter на стероидах. Вы можете фильтровать по tags используя операторы, такие как < , > , == и != .
  • Внутри filter есть некоторые конкретные ключевые слова, такие как _measurement используемые самой базой данных. В этом случае он фильтруется по измерению h2o_temperature .
  • limit(10) возвращает 20 строк в этом случае. Что здесь происходит? Это одно из первых различий в том, как мы создали язык запросов. Существует неявная group by * которая группируется по серии. В этом случае есть две серии: h2o_temperature,location=santa_monica и h2o_temperature,location=coyote_creek . Если вам нужна конкретная серия, вы должны добавить .filter(exp:{"_measurement"=="h2o_temperature" AND "location" ==
    "coyote_creek"})
    .filter(exp:{"_measurement"=="h2o_temperature" AND "location" ==
    "coyote_creek"})
    .filter(exp:{"_measurement"=="h2o_temperature" AND "location" ==
    "coyote_creek"})
    .

Некоторые важные решения, лежащие в основе языка запросов:

  • Порядок аргументов для функции не важен. Каждый аргумент имеет имя и не является обязательным.
  • Используйте " везде», чтобы избежать несоответствия между одинарными и двойными кавычками.

IFQL упрощает каждый запрос от определенного синтаксиса до JSON AST. Вы можете получить AST для вашего конкретного запроса, добавив запрос param analyze=true .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
19:56 $ curl -s -XPOST --data-urlencode 'q=from(db:"NOAA_water_database").range(start: 200h).count()' http://localhost:8093/query?analyze=true | jq
{
  "operations": [
    {
      "id": "from0",
      "kind": "from",
      "spec": {
        "database": "NOAA_water_database",
        "hosts": null
      }
    },
    {
      "id": "range1",
      "kind": "range",
      "spec": {
        "start": "200h0m0s",
        "stop": "now"
      }
    },
    {
      "id": "count2",
      "kind": "count",
      "spec": {}
    }
  ],
  "edges": [
    {
      "parent": "from0",
      "child": "range1"
    },
    {
      "parent": "range1",
      "child": "count2"
    }
  ]
}

README.md внутри проекта IFQL документирует все остальные доступные функции.

Зарегистрируй бесплатный аккаунт Codeship

Масштабируемость

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

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

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

1
2
3
4
5
6
7
8
00:04 $ ./bin/ifqld --help
Usage:
  ifqld [OPTIONS]
 
Options for the IFQLD server
 
Application Options:
  -h, --host=               influx hosts to query from. Can be specified more than once for multiple hosts. (default: localhost:8082) [$HOSTS]

Используя аргумент CLI --host= или переменную среды $HOSTS вы можете указать более одного бэкэнда. Это означает, что если вы работаете с версией с открытым исходным кодом и можете управлять разделением данных поверх большего количества баз данных, вы можете сортировать данные по горизонтали.

Дорожная карта

Проект нестабилен и быстро развивается. API и результаты могут меняться в зависимости от вашего опыта работы с языком запросов. Идея состоит в том, чтобы заблокировать API в начале 2018 года. Если вы являетесь активным пользователем InfluxDB, попробуйте его и не стесняйтесь открывать PR или сообщать о своем сценарии использования, чтобы помочь нам улучшить синтаксис.

Опубликовано на Java Code Geeks с разрешения Джанлуки Арбеццано, партнера нашей программы JCG. Смотрите оригинальную статью здесь: Как сделать запрос InfluxDB

Мнения, высказанные участниками Java Code Geeks, являются их собственными.