2

我想存储时间序列数据,例如超过 6 个月的 CPU 使用率(将每 2 分钟轮询一次 CPU 使用率,因此稍后我可以获得多个分辨率,例如 - 1 周,1 个月,甚至更高的分辨率,5 分钟,ETC)。

我正在使用 Perl,我不想使用 RRDtool 或关系数据库,我正在考虑使用某种具有以下属性的循环缓冲区(环形缓冲区)来实现我自己的:

  1. 6 个月 = 186 天 = 4,464 小时 = 267,840 分钟。
  2. 将其分为 2 分钟部分:267,840 / 2 = 133,920。
  3. 133,920 是环形缓冲区大小。
  4. 环形缓冲区中的每个元素都将是一个 hashref,其键为纪元(使用 轻松转换为日期时间localtime),值是该给定时间的 CPU 使用率。
  5. 我将序列化这个环形缓冲区(Storable我猜使用)

还有其他建议吗?谢谢,

4

2 回答 2

10

我怀疑你多虑了。为什么不使用每个时间间隔一行的平面(例如)制表符分隔文件,每行包含时间戳和 CPU 使用率?这样,您可以在收集新条目时将它们附加到文件中。

如果您想自动丢弃超过 6 个月的数据,您可以通过为每天(或每周或每月或其他任何时间)使用单独的文件并删除旧文件来做到这一点。这比每次都读取和重写整个文件效率更高。


在 Perl 中编写和解析此类文件是微不足道的。这是一些示例代码,我想不到:

写作:

use strict;
use warnings;
use POSIX qw'strftime';

my $dir = '/path/to/log/directory';

my $now = time;
my $date = strftime '%Y-%m-%d', gmtime $now;  # ISO 8601 datetime format
my $time = strftime '%H:%M:%S', gmtime $now;

my $data = get_cpu_usage_somehow();

my $filename = "$dir/cpu_usage_$date.log";

open FH, '>>', $filename
    or die "Failed to open $filename for append: $!\n";

print FH "${date}T${time}\t$data\n";

close FH or die "Error writing to $filename: $!\n";

阅读:

use strict;
use warnings;
use POSIX qw'strftime';

my $dir = '/path/to/log/directory';

foreach my $filename (sort glob "$dir/cpu_usage_*.log") {
    open FH, '<', $filename
        or die "Failed to open $filename for reading: $!\n";
    while (my $line = <FH>) {
        chomp $line;
        my ($timestamp, $data) = split /\t/, $line, 2;
        # do something with timestamp and data (or save for later processing)
    }
}

(注意:我现在无法测试这些示例程序中的任何一个,因此它们可能包含错误或拼写错误。使用风险自负!)

于 2012-09-08T22:18:55.893 回答
2

正如@Borodin 建议的那样,使用 SQLite 或这里DBM::Deep推荐的。

如果您想坚持使用 Perl 本身,请使用DBM::Deep

一个独特的平面文件数据库模块,用纯 perl 编写。... 可以处理数百万个键和无限级别,而不会显着减速。用纯 perl 从头开始​​编写——这不是围绕基于 C 的 DBM 的包装器。与 Unix、Mac OS X 和 Windows 的开箱即用兼容性。

您提到了对存储的需求,这可以通过@llmari 提倡的简单文本文件来满足。(当然,使用 CSV 格式可以在电子表格中轻松操作文件。)

但是,如果您计划收集大量数据,并且希望最终能够以良好的性能查询它,那么请使用为此目的设计的工具。

于 2012-09-10T01:32:31.410 回答