InfluxDB — это популярная база данных временных рядов, и я здесь, чтобы показать вам, как ее запрашивать. Он использует SQL-подобный (или, если честно, «почти-SQL») язык.
1
|
SELECT * FROM "foodships" WHERE time > now() - 1h |
Этот язык работает и поддерживается в InfluxDB с первого дня, и у него есть как плюсы, так и минусы:
- Новым пользователям легко взаимодействовать с базой данных на языке, который они уже знают. SQL популярен, и многие разработчики уже знают его. Этот синтаксис запросов помог InfluxDB расти в первые дни.
- Как я уже говорил, InfluxQL — это язык «amost-SQL». Написание языка SQL-запросов не простая работа. Одна из проблем заключается в том, что администраторы баз данных имеют некоторые ожидания от SQL, но наш язык не полностью совместим с SQL. Это создает много несоответствий и сомнений .
- Одной из характеристик базы данных временных рядов является то, что запись не может блокировать чтение, а чтение не может блокировать запись. Это необходимая вещь. Ваши устройства IOT или ваши серверы всегда будут записывать метрики, а ваша панель мониторинга, аналитические инструменты и менеджеры предупреждений будут считывать данные из базы данных. InfluxDB нужно что-то более масштабируемое.
- На данный момент механизм хранения и язык запросов находятся в одном проекте, который блокирует быструю итерацию кода, который мы хотели бы иметь. Язык запросов развивается намного быстрее по сравнению с механизмом хранения. Движок нуждается в стабильности, но язык запросов нуждается в большем количестве функций и возможностей.
- InfluxQL нуждается в ре-архитектуре, потому что команда не смогла реализовать все удивительные идеи, требуемые сообществом.
- В настоящее время SQL очень прост в изучении, но в нашем стеке есть еще один DSL-доступ: скрипт TICK, используемый Kapacitor для отправки предупреждений и уменьшения количества ваших серий.
- 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
|
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:
с InfluxQL:
-500000h).limit(n: 10)
-
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, являются их собственными. |