6

我有很多分析数据,我希望每隔一段时间(比如说一分钟)汇总一次。数据被发送到一个将其存储在 ETS 表中的进程,并且每隔一段时间,一个计时器就会向它发送一条消息处理表并删除旧数据。

问题是传入的数据量变化很大,我基本上需要做两件事:

  • 如果传入的数据量太大,则丢弃最旧的数据并推送新数据。这可以看作是一个固定大小的队列,如果数据量达到限制,队列将开始从前面,因为新数据排在后面。
  • 如果队列未满,但数据已在那里放置了一段时间,则自动丢弃它(在固定超时后)。

如果保持这两个条件,我基本上可以假设该表具有恒定大小,并且其中的所有内容都比 X 新。

问题是我还没有找到一种有效的方法来一起做这两件事。我知道我可以使用匹配规范来删除所有早于 X 的条目,如果索引是时间戳,这应该会非常快。虽然我不确定这是否是定期修剪桌子的最佳方式。

第二个问题是将总表大小保持在一定的限制下,我不太确定该怎么做。想到的一个解决方案是在每次插入时使用自动增量字段,并且在修剪表时,查看第一个和最后一个索引,计算差异,然后再次使用匹配规范删除低于阈值的所有内容。

说了这么多,感觉我可能会使用 ETS 表来做一些它不是设计用来做的事情。有没有更好的方法来存储这样的数据,或者我是否正确地解决了这个问题?

4

3 回答 3

2

您可以使用 确定占用的数据量ets:info(Tab, memory)。结果是字数。但是有一个问题!如果您要存储二进制文件,则仅包含堆二进制文件。因此,如果您存储的大部分是普通的 Erlang 术语,您可以使用它并使用您所描述的时间戳,这是一种可行的方法。对于以字节为单位的大小,只需乘以erlang:system_info(wordsize).

于 2015-05-31T12:22:26.730 回答
1

我没有将 ETS 用于这样的事情,但在其他 NoSQL DB (DynamoDB) 中,一个简单的解决方案是使用多个表:如果您保留 24 小时的数据,则保留 24 个表,一天中的每个小时一个. 当您要删除数据时,请删除一个完整的表。

于 2015-05-31T11:43:32.190 回答
0

我会做以下事情:创建一个服务器负责

  • 接收所有数据存储消息。该消息应该由客户端进程加盖时间戳(因此它是否在消息队列中等待一点并不重要)。然后服务器将然后存储在 ETS 中,配置为 ordered_set 并使用时间戳,转换为整数,作为键(如果时间戳由函数 erlang:now 在一个单独的 VM 中传递,它们将不同,如果你正在使用多个节点,那么您将需要添加一些信息,例如节点名称以保证唯一性)。
  • 接收一个滴答声(例如使用 timer:send_interval),然后处理在最后 N 微秒内收到的消息(使用 Key = 当前时间 - N)并寻找 ets:next(Table,Key),并继续到最后一条消息. 最后,您可以通过 ets:delete_all_objects(Table) 丢弃所有消息。如果您必须添加诸如节点名称之类的信息,仍然可以使用下一个函数(例如键是 {TimeStamp:int(),Node:atom()} 您可以将其与 {Time:int( ),0} 因为一个数比任何原子都小)
于 2015-05-31T21:18:13.870 回答