使用PHP和InfluxDB入门

导航到

本文由Cameron Pavey撰写,他是一名居住和工作的全栈开发者。向下滚动查看他的图片和简介。

作为一名开发者,您可能会遇到传统关系型数据库的文档存储无法满足需求的情况。如果您需要存储随时间变化的数据点,您可能需要一个时间序列数据库。

时间序列数据库非常适合存储系统监控数据、分析报告数据和来自心率传感器和温度传感器等传感器的数据。任何您想要查看数据随时间趋势的情况,时间序列数据库都能满足您的需求。

InfluxDB 是一个强大、开源的时间序列平台,拥有众多语言的客户端库,可以轻松地将时间序列数据驱动的功能添加到您的应用程序中。

在本指南中,您将学习如何使用PHP应用程序设置InfluxDB,连接到数据库的基本知识,写入数据、读取数据,以及连接完成后的操作。

InfluxDB是一个强大、开源的时间序列平台,拥有众多语言的客户端库,可以轻松地将时间序列数据驱动的功能添加到您的应用程序中。

InfluxDB客户端库

对于本指南,您将使用官方PHP库来连接到您的InfluxDB实例。此库适用于InfluxDB 2.x和1.8+。对于1.7及更早版本,您需要使用旧的InfluxDB客户端库;但是,它与此指南不兼容。

要开始,您需要满足一些先决条件。当然,您需要一个正在运行的InfluxDB实例,以便将应用程序指向它。本指南使用InfluxDB v2.0和通过Homebrew安装在macOS系统上的PHP 8编写。

尽管如此,这些步骤也适用于其他操作系统和安装来源,如Docker。您可以通过InfluxDBPHP的官方文档获取适合您的设置的安装选项。

如果您还没有为这个指南创建存放代码的目录,请现在创建一个。一旦有了目录,您就可以通过在终端执行以下命令使用composer安装InfluxDB客户端

$ composer require influxdata/influxdb-client-php

您还需要在InfluxDB中创建一个桶来存储您的数据。本指南假设您的组织和桶都命名为“influx”,但您可以随意命名。

如果您之前没有使用过InfluxDB,安装后,导航到[localhost:8086],您将需要设置初始用户详细信息。然后您可以使用这些详细信息完成本指南。

建立连接

要使用您的InfluxDB实例在PHP应用程序中,您需要使用与Composer下载的客户端库建立连接。

首先,您需要创建客户端实例并提供其实例的详细信息。为此,您可以创建一个变量,如下所示

# First, let's make use of Composer so that we can access the Library
require __DIR__ . '/vendor/autoload.php';

# You can generate a Token from the "Tokens Tab" in the UI
$token = '...';
$org = 'influx';
$bucket = 'influx';

# Next, we will instantiate the client and establish a connection
$client = new InfluxDB2\Client([
	"url" => "https://127.0.0.1:8086", // url and port of your instance
	"token" => $token,
	"bucket" => $bucket,
	"org" => $org,
	"precision" => InfluxDB2\Model\WritePrecision::NS,
]);

$writeApi = $client->createWriteApi();

要检查InfluxDB服务器的状态以确保一切按预期工作,您可以使用$client->health();。此函数将执行influx ping,并返回一个描述服务器状态以及它是否准备好接收查询的对象。

对于本指南,您将看到可用于读取和写入InfluxDB数据的各种选项。为了帮助说明这些示例,请参阅以下JSON对象。这是我们希望添加到我们的数据库中的数据点的粗略估计。

{
  "measurement": "temp_c",
  "tags": [
	"location": "Melbourne"
  ],
  "fields": [
	"degrees": 14,
	"humidity": 0.57
  ]
}

插入数据

一旦您设置了实例并在PHP应用程序中设置了初始化代码,您就可以开始插入数据。作为时序数据库,InfluxDB的行为与关系型数据库略有不同。您不必严格遵循预定义的模式,可以更灵活地插入数据。数据被分成桶。在给定的桶中,您有测量值作为数据点,对于给定的测量值,您可以有字段值和标签。

值得注意的是,测量值和标签是索引的,而字段值不是,因此建议以这种方式结构您的数据,即您的常用查询元数据编码在标签中。关于有效数据布局设计有很多细微差别,因此建议在设计模式之前阅读来自InfluxData的关于该主题的官方文档

然而,目前我们并不真正关心这些细节。我们的目的是了解如何将InfluxDB的力量带到我们的PHP应用程序中。因此,我们将坚持使用简单的模式。

当涉及到通过PHP客户端插入数据时,有三种主要的方法。

使用InfluxDB行协议

行协议是一个由字符串表示的标准数据格式。行协议由一些离散元素组成,您可以使用这些元素提供要插入的数据。

measurementName,tagKey=tagValue fieldKey="fieldValue" 1465839830100400200
--------------- --------------- --------------------- -------------------
   	|           	|              	|                	|
  Measurement   	Tag set       	Field set        	Timestamp

在这里,您可以看到行协议的元素。第一个值是测量值,后面跟着一个逗号分隔的标签键值对列表,然后是一个逗号分隔的字段键值对列表,最后是数据点的时间戳。

$data = "temp_c,location=Melbourne degrees=14,humidity=0.57";

$writeApi->write($data, WritePrecision::S, $bucket, $org);

这种方法在概念上最简单,当您已经将数据处理成行协议格式时非常有用,例如来自另一个API或文本文件。

使用数据点

如果您想避免手动构建行协议字符串,您的下一个选择是使用客户端库提供的数据点构建器,以正确序列化您的数据,使其成为PHP的原生方式。这是一种构建单个数据点的简单、声明式方法,如果您只有少量标签和字段,这是一种插入数据的好方法。

$point = Point::measurement('temp_c')
  ->addTag('location', 'Melbourne')
  ->addField('degrees', 14)
  ->addField('humidity', 0.57)
  ->time(microtime(true));

$writeApi->write($point, WritePrecision::S, $bucket, $org);

使用数组结构

您还可以使用数组结构插入数据。这与之前使用数据点的选项类似,但更有利于添加多个标签和字段。这是一个很好的选择,尤其是当与PHP的数组函数结合使用时,这些函数可以轻松地从任何来源提取和转换数据,并将其映射到更适合存储在InfluxDB中的格式。

$dataArray = ['name' => 'temp_c',
  'tags' => ['location' => 'Melbourne'],
  'fields' => ['degrees' => 14, 'humidity' => 0.57],
  'time' => microtime(true)];

$writeApi->write($dataArray, WritePrecision::S, $bucket, $org);

查询数据

现在您已经在InfluxDB中存储了一些数据,是时候将其查询出来。主要有两种方式来实现这一点:使用表格结构或流。无论哪种方式,我们首先需要实例化一个查询客户端。

$queryApi = $client->createQueryApi();

InfluxDB查询使用Flux查询语言编写。如果您不熟悉它或需要复习,请参考官方文档

表格结构

您可以以表格结构的方式查询数据。

$query = "from(bucket: \"$bucket\")
	|> range(start: -1h)
	|> filter(fn: (r) => r._measurement == \"temp_c\")";

$records = $queryApi->query($query, $org);

这将返回一个InfluxTable对象的数组,代表查询数据的CSV格式。

queryStream方法

您的另一种选择是使用queryStream方法,这将返回一个对象,允许您使用生成器模式访问CSV数据。这对于内存有限的情况非常适用,例如资源有限、数据集较大或出于个人偏好。

$query = "from(bucket: \"$bucket\")
	|> range(start: -1h)
	|> filter(fn: (r) => r._measurement == \"temp_c\")";

$parser = $queryApi->queryStream($query, $org);

foreach($parser->each() as $record) {
  ...
}

整合所有内容

现在您已经了解了如何设置客户端库、写入数据以及读取数据,是时候将这些部分整合在一起了。尝试在一个脚本中写入一些数据点、读取它们并对它们执行一些逻辑。

<?php
use InfluxDB2\Model\WritePrecision;

require __DIR__ . '/vendor/autoload.php';

# You can generate a Token from the "Tokens Tab" in the UI
$token = '...'; # your token here
$org = 'influx';
$bucket = 'influx';

$client = new InfluxDB2\Client([
	"url" => "https://127.0.0.1:8086", // url and port of your instance
	"token" => $token,
]);

// The base data we will be inserting
$rawData = [
	["temp" => 8, 'humidity' => .57],
	["temp" => 8, 'humidity' => .59],
	["temp" => 7, 'humidity' => .60],
	["temp" => 7, 'humidity' => .58],
	["temp" => 7, 'humidity' => .54],
	["temp" => 9, 'humidity' => .53],
	["temp" => 10, 'humidity' => .55],
	["temp" => 10, 'humidity' => .59],
	["temp" => 11, 'humidity' => .60],
];

$writeApi = $client->createWriteApi();
foreach ($rawData as $index => $datum) {
	$dataArray = [
    	'name' => 'temp_c',
    	'tags' => ['location' => 'Melbourne'],
    	'fields' => ['degrees' => $datum['temp'], 'humidity' => $datum['humidity']],
    	'time' => microtime(true) - (7200 * $index), // we will populate data going back by the hour
	];
	$writeApi->write($dataArray, WritePrecision::S, $bucket, $org);
}

$queryApi = $client->createQueryApi();
$query = "from(bucket: \"$bucket\")
	|> range(start: -12h)
	|> filter(fn: (r) => r._measurement == \"temp_c\")";

$tables = $queryApi->query($query, $org);

$records = [];
foreach ($tables as $table) {
	foreach ($table->records as $record) {
    	// because we will have multiple fields at the same second in time, we need to merge the data into a single array after we query it out
    	$row = key_exists($record->getTime(), $records) ? $records[$record->getTime()] : [];
    	$records[$record->getTime()] = array_merge($row, [$record->getField() => $record->getValue()]);
	}
}

结论

希望这能帮助您更清楚地了解如何使用InfluxDB与PHP应用程序或脚本结合使用。InfluxDB和PHP客户端还有很多功能,如果您想了解更多,请参阅官方文档。

关于作者

Cmeraon Pavey shows how to get started with InfluxDB and PHP

Cameron是一位全栈开发者,生活在墨尔本。他致力于理解优质代码、开发人员生产力和工作满意度的复杂性。