存储时间序列数据,无需数据库

时间:2012-09-08 22:05:50

标签: perl datetime time-series

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

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

  1. 6个月= 186天= 4,464小时= 267,840分钟。
  2. 将其分为2分钟:267,840 / 2 = 133,920。
  3. 133,920是环形缓冲区大小。
  4. ring-buffer中的每个元素都是一个hashref,其密钥为epoch(使用localtime轻松转换为日期时间),该值为该给定时间的CPU使用率。
  5. 我将序列化此环缓冲区(使用Storable我猜)
  6. 还有其他建议吗? 谢谢,

2 个答案:

答案 0 :(得分:10)

我怀疑你是在思考这个问题。为什么不使用平坦(例如)TAB分隔的文件,每个时间间隔一行,每行包含时间戳和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)
    }
}

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

答案 1 :(得分:2)

正如@Borodin建议的那样,使用SQLite或DBM::Deep作为推荐here

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

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

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

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