使用PHP和InfluxDB入门
作者:社区 / 产品, 用例, 开发者, 入门
2021年9月13日
导航到
本文由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。您可以通过InfluxDB和PHP的官方文档获取适合您的设置的安装选项。
如果您还没有为这个指南创建存放代码的目录,请现在创建一个。一旦有了目录,您就可以通过在终端执行以下命令使用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客户端还有很多功能,如果您想了解更多,请参阅官方文档。
关于作者
Cameron是一位全栈开发者,生活在墨尔本。他致力于理解优质代码、开发人员生产力和工作满意度的复杂性。