将实时数据存储到1000个文件中

时间:2009-05-29 13:19:01

标签: c# real-time

我有一个程序可以接收1000个主题的实时数据。它平均每秒收到5000条消息。每条消息由两个字符串,一个主题和一个消息值组成。我想保存这些字符串以及指示消息到达时间的时间戳。

我在'Core 2'硬件上使用32位Windows XP并使用C#编程。

我想将这些数据保存到1000个文件中 - 每个主题一个。我知道很多人都想告诉我将数据保存到数据库中,但我不想走这条路。

我考虑过几种方法:

1)打开1000个文件,并在数据到达时写入每个文件。我对此有两个担忧。我不知道是否可以同时打开1000个文件,我不知道这会对磁盘碎片产生什么影响。

2)写入一个文件,并以某种方式 - 稍后处理它以生成1000个文件。

3)将其全部保存在RAM中直到当天结束,然后一次写入一个文件。我认为如果我有足够的内存,这将很有效,尽管我可能需要移动到64位以超过2 GB的限制。

你会如何解决这个问题?

11 个答案:

答案 0 :(得分:10)

我无法想象为什么你不想为此使用数据库。这就是他们的目的。他们相当擅长。

如果您不愿意走这条路线,将它们存储在RAM中并每小时将它们旋转到磁盘可能是一种选择,但请记住,如果您绊倒电源线,则会丢失大量数据。

严重。数据库吧。

编辑我应该补充一点,如果你准备好硬件,那么获得一个强大的,复制的和完整的数据库支持的解决方案将花费你不到一天的时间。

在任何其他环境中执行此级别的交易保护将花费您数周时间来设置和测试。

答案 1 :(得分:4)

与n8wrl一样,我也会推荐一个DB。但如果你真的不喜欢这个功能......

让我们找到另一种解决方案; - )

在最小的步骤中,我将采取两个线程。首先是一个工作者,接收所有数据并将每个对象(时间戳,两个字符串)放入队列中。

另一个线程将检查此队列(可能是按事件或通过检查Count属性的信息)。该线程将使每个对象出列,打开特定文件,将其写下来,关闭文件并继续下一个事件。

通过第一种方法,我将开始并看一下性能。如果它很糟糕,做一些计量,问题出在哪里并尝试完成它(将打开的文件放入字典(name,streamWriter)等)。

但另一方面,DB对于这个问题会很好...... 一个表,四列(id,时间戳,主题,消息),一个关于主题的附加索引,准备就绪。

答案 2 :(得分:2)

我想更多地探讨为什么你不使用数据库 - 他们在这样的事情上是伟大的!但是你的选择......

  1. 1000个打开的文件句柄听起来不太好。忘记磁盘碎片 - 操作系统资源会很糟糕。
  2. 这接近db-ish-ness!听起来也比它的价值更麻烦。
  3. RAM =不稳定。你花了一整天积累数据,并在下午5点停电。
  4. 我该如何处理? D B!因为那时我可以查询索引,分析等等。

    :)

答案 3 :(得分:2)

首先计算带宽! 5000条消息/秒,每条2kb = 10mb /秒。每分钟 - 600mb。那么你可以把它放在内存中。然后每小时冲洗一次。

编辑:纠正错误。对不起,我的坏。

答案 4 :(得分:2)

我同意凯尔的意见,并选择像PI这样的套餐产品。请注意PI非常昂贵。

如果您正在寻找自定义解决方案,我会与Stephen's进行一些修改。让一台服务器接收消息并将它们放入队列中。您不能使用文件将消息传递给其他进程,因为您将不断发生锁定问题。可能使用类似MSMQ(MS消息队列)的东西,但我不确定速度。

我还建议使用db来存储您的数据。您可能希望将数据批量插入到数据库中,因为我认为您需要一些重要的硬件来允许SQL每秒执行5000次事务。你最好做一个批量插入,每次说出累积在队列中的10000条消息。

数据大小:

平均消息~50字节 - > 小日期时间= 4字节+主题(约10个字符非unicode)= 10字节+消息 - > 31个字符(非unicode)= 31个字节。

50 * 5000 = 244kb / sec - > 14mb / min - > 858mb /小时

答案 5 :(得分:2)

我同意Oliver,但我建议修改:拥有1000个队列,每个主题/文件一个。一个线程接收消息,对它们加时间戳,然后将它们粘贴到适当的队列中。另一个只是在队列中旋转,看看他们是否有数据。如果是,则读取消息,然后打开相应的文件并将消息写入其中。关闭文件后,它会移动到下一个队列。这样做的一个优点是,如果无法跟上流量,您可以添加额外的文件写入线程。我可能首先尝试设置写入阈值,但是(延迟处理队列直到它有N条消息)来批量写入。这样你就不会陷入打开和关闭文件只能写一两条消息。

答案 6 :(得分:2)

也许您不希望数据库安装的开销?

在这种情况下,您可以尝试a filesystem-based database like sqlite

  

SQLite是一个软件库   实现一个独立的,   无服务器,零配置,   事务性SQL数据库引擎。   SQLite是部署最广泛的SQL   世界上的数据库引擎。该   SQLite的源代码在   公共领域。

答案 7 :(得分:1)

我会制作两个独立的程序:一个用于接收传入的请求,格式化它们,然后将它们写入一个文件,另一个用于从该文件中读取并写出请求。通过这种方式执行操作,您可以在仍然实时处理传入请求的同时最小化打开的文件句柄数。如果您制作了第一个程序格式,则输出正确,然后将其处理为单个文件应该很简单。

答案 8 :(得分:1)

我会考虑购买实时数据历史数据包。类似PI System或Wonderware Data Historian的东西。我之前在文件和MS SQL数据库中尝试过这样的事情并且结果并不好(这是客户要求,我不建议)。这些产品具有API,甚至还有包,您可以像对待SQL一样对数据进行查询。

它不允许我发布超链接,所以只是谷歌这两个产品,你会发现它们的信息。

修改

如果您确实使用数据库,大多数人都建议我为每个主题推荐一个表用于历史数据,并考虑表分区,索引以及您要存储数据的时间。

例如,如果您要为每个主题存储一天的价值和一个表,您将看到每秒5次更新x 60秒一小时60分钟x 24小时=每天432000条记录。导出数据后,我想你必须清除第二天的数据,这将导致锁定,因此你必须排队写入数据库。然后,如果要重建索引,以便可以对其进行任何查询,这将导致架构修改锁定和MS SQL Enterprise Edition进行联机索引重建。如果你不是每天都清除数据,你必须确保有足够的磁盘空间来投入它。

基本上我说的是衡量购买可靠产品的成本,而不是建立自己的产品。

答案 9 :(得分:1)

我会保留传入消息的缓冲区,并定期在单独的线程上顺序写入1000个文件。

答案 10 :(得分:0)

如果您不想使用数据库(我愿意,但假设您没有),我会将记录写入单个文件,追加操作尽可能快,并使用单独的进程/服务将文件拆分为1000个文件。您甚至可以每隔X分钟翻转一次文件,例如,每隔15分钟就会启动一个新文件,另一个进程会开始将它们拆分为1000个单独的文件。

这一切确实提出了为什么不是数据库的问题,以及为什么你需要1000个不同的文件 - 你可能有一个很好的理由 - 但话说回来,也许你应该重新思考你的策略并确保它是健全的在你沿着这条道路前进之前的推理。