Использование InfluxDB с Java

Использование InfluxDB с Java

1. обзор

InfluxDB is a high-performance store for time-series data. Он поддерживает вставку и запросы данных в реальном времени с помощью языка запросов, подобного SQL.

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

2. Настроить

Чтобы подключиться к базе данных, нам нужно добавить запись в наш файлpom.xml:


    org.influxdb
    influxdb-java
    2.8

Последнюю версию этой зависимости можно найти наMaven Central.

Нам также понадобится экземпляр InfluxDB. Инструкции дляdownloading and installing a database можно найти на веб-сайтеInfluxData.

3. Подключение к серверу

3.1. Создание подключения

Для создания соединения с базой данных требуется передать URLString и учетные данные пользователя в фабрику соединений:

InfluxDB influxDB = InfluxDBFactory.connect(databaseURL, userName, password);

3.2. Проверка подключения

Communications with the database are performed over a RESTful API, поэтому они непостоянны.

API предлагает специальную услугу «ping» для подтверждения работоспособности соединения. Если соединение хорошее, ответ содержит версию базы данных. В противном случае он содержит“unknown”.

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

Pong response = this.influxDB.ping();
if (response.getVersion().equalsIgnoreCase("unknown")) {
    log.error("Error pinging server.");
    return;
}

3.3. Создание базы данных

Создание базы данных InfluxDB аналогично созданию базы данных на большинстве платформ. But we need to create at least one retention policy before using it.с

A retention policy tells the database how long a piece of data should be stored. Временные ряды, такие как статистика ЦП или памяти, как правило, накапливаются в больших наборах данных.

Типичная стратегия управления размером баз данных временных рядов -downsampling. «Необработанные» данные сохраняются с высокой скоростью, суммируются, а затем удаляются через короткое время.

Retention policies simplify this by associating a piece of data with an expiration time. InfluxData имеетin-depth explanation на своем сайте.

После создания базы данных мы добавим одну политику с именемdefaultPolicy.. Она просто будет хранить данные в течение 30 дней:

influxDB.createDatabase("example");
influxDB.createRetentionPolicy(
  "defaultPolicy", "example", "30d", 1, true);

Чтобы создать политику хранения, нам понадобятсяname,,database, иinterval,areplication factor (который должен быть 1 для базы данных с одним экземпляром) иbooleanуказывает, что это политика по умолчанию.

3.4. Установка уровня ведения журнала

Внутри InfluxDB API используетRetrofit и предоставляет интерфейс для функции ведения журнала Retrofit черезlogging interceptor.

Итак, мы можем установить уровень ведения журнала, используя:

influxDB.setLogLevel(InfluxDB.LogLevel.BASIC);

И теперь мы можем видеть сообщения, когда мы открываем соединение и проверяем его:

Dec 20, 2017 5:38:10 PM okhttp3.internal.platform.Platform log
INFO: --> GET http://127.0.0.1:8086/ping

Доступные уровни:BASIC,FULL,HEADERS иNONE..

4. Добавление и получение данных

4.1. Точки

Итак, теперь мы готовы начать вставку и получение данных.

Базовая единица информации в InfluxDB - этоPoint,, который по сути является меткой времени и картой значения ключа.

Давайте посмотрим на точку, содержащую данные об использовании памяти:

Point point = Point.measurement("memory")
  .time(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
  .addField("name", "server1")
  .addField("free", 4743656L)
  .addField("used", 1015096L)
  .addField("buffer", 1010467L)
  .build();

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

Давайте посмотрим, как добавить это в базу данных.

4.2. Написание партий

Time series data tends to consist of many small points, and writing those records one at a time would be very inefficient. Предпочтительный метод - собирать записи в пакеты.

API InfluxDB предоставляет объектBatchPoint:

BatchPoints batchPoints = BatchPoints
  .database(dbName)
  .retentionPolicy("defaultPolicy")
  .build();

Point point1 = Point.measurement("memory")
  .time(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
  .addField("name", "server1")
  .addField("free", 4743656L)
  .addField("used", 1015096L)
  .addField("buffer", 1010467L)
  .build();

Point point2 = Point.measurement("memory")
  .time(System.currentTimeMillis() - 100, TimeUnit.MILLISECONDS)
  .addField("name", "server1")
  .addField("free", 4743696L)
  .addField("used", 1016096L)
  .addField("buffer", 1008467L)
  .build();

batchPoints.point(point1);
batchPoints.point(point2);
influxDB.write(batchPoints);

Мы создаемBatchPoint, а затем добавляем к немуPoints. Мы установили временную метку для нашей второй записи равной 100 миллисекундам в прошлом, поскольку временные метки являются основным индексом. Если мы отправим две точки с одинаковой отметкой времени, останется только одна.

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

4.3. Написание по одному

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

Давайте включим пакетный режим с одним вызовом соединения InfluxDB:

influxDB.enableBatch(100, 200, TimeUnit.MILLISECONDS);

Мы включили пакетирование 100 для вставки на сервер или отправки того, что у него есть каждые 200 миллисекунд.

С включенным пакетным режимом мы все еще можем писать по одному. Однако требуется дополнительная настройка:

influxDB.setRetentionPolicy("defaultPolicy");
influxDB.setDatabase(dbName);

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

influxDB.write(point);

Before we enqueue individual points, we need to set a database (аналогично командеuse в SQL)and set a default retention policy. Поэтому, если мы хотим воспользоваться преимуществом понижающей дискретизации с несколькими политиками хранения, создание пакетов - это лучший способ.

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

influxDB.disableBatch();

Закрытие соединения также отключит пул потоков:

influxDB.close();

4.4. Сопоставление результатов запроса

Запросы возвращаютQueryResult, которые мы можем сопоставить с POJO.

Прежде чем мы рассмотрим синтаксис запроса, давайте создадим класс для хранения нашей статистики памяти:

@Measurement(name = "memory")
public class MemoryPoint {

    @Column(name = "time")
    private Instant time;

    @Column(name = "name")
    private String name;

    @Column(name = "free")
    private Long free;

    @Column(name = "used")
    private Long used;

    @Column(name = "buffer")
    private Long buffer;
}

Класс аннотируется@Measurement(name = “memory”), что соответствуетPoint.measurement(“memory”), которое мы использовали для создания нашегоPoints.

Для каждого поля в нашемQueryResult мы добавляем аннотацию@Column(name = “XXX”) с именем соответствующего поля.

QueryResults отображаются в POJO сInfluxDBResultMapper.

4.5. Запрос InfluxDB

Итак, давайте использовать наш POJO с точками, которые мы добавили в базу данных в нашем двухточечном пакете:

QueryResult queryResult = connection
  .performQuery("Select * from memory", "example");

InfluxDBResultMapper resultMapper = new InfluxDBResultMapper();
List memoryPointList = resultMapper
  .toPOJO(queryResult, MemoryPoint.class);

assertEquals(2, memoryPointList.size());
assertTrue(4743696L == memoryPointList.get(0).getFree());

Запрос показывает, как наше измерение с именемmemory сохраняется в виде таблицыPoints, из которой мы можем использоватьselect.

InfluxDBResultMapper принимает ссылку наMemoryPoint.class сQueryResult и возвращает список точек.

После сопоставления результатов мы проверяем, что получили два, проверяя длинуList, полученную в результате запроса. Затем мы смотрим на первую запись в списке и видим объем свободной памяти для второй точки, которую мы вставили. The default ordering of query results from InfluxDB is ascending by timestamp.

Давайте изменим это:

queryResult = connection.performQuery(
  "Select * from memory order by time desc", "example");
memoryPointList = resultMapper
  .toPOJO(queryResult, MemoryPoint.class);

assertEquals(2, memoryPointList.size());
assertTrue(4743656L == memoryPointList.get(0).getFree());

Добавлениеorder by time desc меняет порядок наших результатов.

Запросы InfluxDB выглядят очень похоже на SQL. Есть обширный справочникon their site.

5. Заключение

Мы подключились к серверу InfluxDB, создали базу данных с политикой хранения, а затем вставили и получили данные с сервера.

Полный исходный код примеров -over on GitHub.