7

我有一个项目,物理传感器将数据发送到服务器。数据不定期发送 - 在某些东西激活传感器之后,但不低于每 20 分钟一次。在服务器上,数据存储在 Posgresql 数据库中。

数据结构如下:

Sensor Table
    sensor name - string
    sensor serial no - string
    sensor type - foreign key to types table

Sensor Data Table
    sensor - foreign key
    timestamp
    value 1 - boolean
    value 2 - boolean
    value 3 - integer
    value 4 - float
    ...

预计总共不超过 100 个请求/秒。数据库中的数据记录应该保留 90 天,在某些情况下甚至更长(不仅仅是我之前想的 2 周)。因此,记录的总数不会超过 120 960 000/14 天。这是“安全”的估计。实际上,它可能会少 10 倍(10 个请求/秒,12 960 000 条记录)。

我需要对数据进行一些分析,例如:

  1. 当新记录出现并且“值 2”为真时做某事
  2. 当传感器 X 的“值 2”为真的时间超过某个声明的时间(50 分钟、1 小时或更长时间)时,做一些事情
  3. 当传感器 X 在 24 小时内“值 2”的总真实时间超过某个声明的时间时执行某些操作
  4. 当传感器 X 的“值 3”为真的时间超过某个声明的时间并且在此期间没有其他 XYZ 类型的传感器处于活动状态时,请执行某些操作...

上面的“声明时间”大于等于1秒。

整个服务器部分是在 Django 中开发的(和 django-rest-framework 来收集数据)。

问题是如何有效地进行此类数据分析,假设应该对数据和时间段进行实时或接近实时(1 秒)的监控以触发所需的操作。

我的想法:

  1. 运行一个进程,每秒查询数据库以查找符合条件的记录并调用特定操作(可能需要超过 1 秒)

  2. 为每种分析类型运行一些单独的进程(eventlet?),然后每 1 秒查询一次数据库并触发特定操作。

  3. 每个传感器运行一个进程,持续向其订阅者报告:我在“值 2”上的正确时间超过 x 秒等。在该传感器的新数据到达后,进程被重置。像 zeromq 这样的发布-订阅解决方案可能会在这里使用吗?

  4. 使用其他/更快的解决方案

    • Mongodb - 问题可能是删除数据后(2 周)mongodb 的文件没有被压缩。
    • Hadoop——对于这类问题来说是不是太大太复杂了?
    • Pandas 和一些 HDF5 存储 - 问题可能在于它是否能够进行我上面描述的分析,并且可能还能够写入文件。但是..也可以与 mongo 一起使用。

提示?

更新。

目前对我来说似乎简单有效的解决方案是:

  1. 数据到达传感器 A 后,运行所有测试并
  2. 以如下方式将测试结果存储在一些“测试”表(或 redis)中:
    • 今天下午 1:15 运行动作“传感器打开时间超过”
    • 今天下午 1:30 运行动作“传感器打开时间超过 24 小时”...
  3. 连续扫描上面的“测试”表,当它是今天下午 1:15 时,然后运行所需的操作,等等。
  4. 当传感器 A 收到新信号时,再次运行所有测试,并重置“测试”表中的数据。

这将要求我在每次请求到达特定传感器时触发测试,但另一方面,我必须每 1 秒扫描一次“测试”表。

更新 2

我发现了 PyTables ( http://www.pytables.org/moin/PyTables ),看起来它非常适合我作为数据存储的用例。

4

4 回答 4

2

我的第一个尝试是在“传感器数据表”上创建一个多列索引,例如:

sensor->timestamp->value1 //Index 1
sensor->timestamp->value2 //Index 2
sensor->timestamp->value3 //Index 3
sensor->timestamp->value4 //Index 4

看看你的 SQL 查询是否足够快。您可以通过 eventlet 或 cron 查询它。从性能的角度来看,只要此查询足够快,您使用哪个并不重要,它很可能是您的瓶颈。

另一个建议是尝试 MySQL 内存表,或 postgre 等价物(PostgreSQL 中的内存表)。

还有一个建议是尝试 Redis。您可以将“传感器数据”存储为排序集的集合;每个传感器 id 和 value 字段一个排序集,并按时间戳对数据进行排序。

 ZADD sensor_id:value1 timestamp value
 ZADD sensor_id:value2 timestamp value

Redis 将需要一些应用程序逻辑来累积数据,但如果它们都适合 RAM,它会非常快。

回复:MongoDB。您可以获得良好的性能。只要您的可查询数据+索引可以放入RAM并且没有太多写锁。尽管运行 2 个提供重叠功能的重量级数据库是一种管理(和编码)负担。鉴于此,压缩并不是真正的问题。您可以在传感器数据上创建 TTL 索引,mongo 将删除 bg 线程中的旧数据。文件大小将在一段时间后保持不变。

希望这可以帮助

于 2013-04-15T14:00:06.370 回答
0

如果您的规则很简单或很少,您可以尝试使用 SQL 触发器来更新存储的视图,这可能会被快速查询。例如,假设您想要检测某个传感器已经激活了给定的时间,您可以有一个表格,其中包含当前激活的传感器的激活时间。每当您存储原始事件时,触发器都会更新这样的表。

类型 3 的规则会更加困难。除非它们很少,并且您可以为每个触发器和视图设置一组触发器和视图,或者预先知道允许的时间段。

于 2013-04-15T15:23:58.780 回答
0

您是否考虑过按问题分桶并流式处理输入数据?

这种类型的示例方法是:

for event in new_events: # new events to be written from the RESTful service
    for test in tests: # known tests you need to perform
        increment/decrement <test.bucket>.<sensor>.<valueX> # update the bucket as necessary
        # e.g. seconds_since_changed.sensor1.value3 += 1
     # additionally, save each record to a standard database for long-term purposes
     # and to be able to rebuild/redo tests as necessary.

这种事务流的理想存储机制是一种非常适合低延迟写入/更新的存储机制。NoSQL 解决方案非常适合此类工作(我个人使用 Redis 进行类似类型的分析,但您绝不会受限于该特定解决方案。)

于 2013-04-15T19:55:50.807 回答
0

选项#4。关系数据库是明显的瓶颈。以更简单的形式安排数据传输(目录中的文件,以传感器名称或任何唯一键命名)。您可以更快地处理,检查时间戳和读取 - 然后在分析后将数据推送到后端的 rdb。

于 2013-04-15T19:40:36.613 回答