【问题标题】:Storing Real Time data into 1000 files将实时数据存储到 1000 个文件中
【发布时间】:2009-05-29 13:19:00
【问题描述】:

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

我在“Core 2”硬件上使用 32 位 Windows XP,并使用 C# 进行编程。

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

我考虑了几种方法:

1) 打开 1000 个文件,并在数据到达时写入每个文件。我对此有两个担忧。不知道能不能同时打开1000个文件,也不知道对磁盘碎片有什么影响。

2) 写入一个文件并在稍后处理它以生成 1000 个文件。

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

你会如何解决这个问题?

【问题讨论】:

    标签: c# real-time


    【解决方案1】:

    我无法想象您为什么不想为此使用数据库。这就是他们建造的目的。他们很擅长。

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

    说真的。将其数据库化。

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

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

    【讨论】:

    • 我仍然担心数据库是否可以平均每秒处理 5,000 个事务。我几乎没有使用数据库的经验——由于不熟悉和担心大量数据的性能,我一直远离它们。存储数据六个月后,我将有很多表...每天,我将创建 1000 个新表(每个主题 1 个),因此在六个月内我将拥有大约 125,000 个表。这是在一台 32 位机器上运行良好的东西吗?
    • 为什么必须为每个主题创建一个?没必要。
    【解决方案2】:

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

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

    至少我会使用两个线程。第一个是worker,接收所有数据并将每个对象(时间戳,两个字符串)放入队列中。

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

    使用第一种方法,我将开始查看性能。如果它很糟糕,请进行一些计量,找出问题所在并尝试完成它(将打开的文件放入字典(名称、streamWriter)等)。

    但另一方面,数据库可以很好地解决这个问题...... 一张表,四列(id,timestamp,topic,message),一个额外的topic索引,准备好了。

    【讨论】:

    • 这将每秒打开和关闭 5000 个文件——如果两个后续消息具有相同的主题,可能会少一些。我认为这行不通,因为第二个线程跟不上。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      我想进一步探讨一下为什么您不想使用数据库 - 他们在这样的事情上非常出色!但是根据您的选择...

      1. 1000 个打开的文件句柄听起来不太好。忘记磁盘碎片 - 操作系统资源会很糟糕。
      2. 这接近于 db-ish-ness!听起来麻烦多于其价值。
      3. RAM = 易失性。您整天都在积累数据,下午 5 点就停电了。

      我将如何处理这个问题? D B!因为那时我可以查询索引,分析等等等等。

      :)

      【讨论】:

      • 数据库每秒可以处理 5000 条消息吗?另外,我听说过——但不是很清楚——DB 不太擅长处理时间序列数据。
      • 当然!保持高交易率的许多策略。时间序列数据,意思是日期+时间数据?绝对的。
      • 实际上 DB 就是为此而构建的。而且它们的扩展性非常好。
      • 完全正确 - 他们已经弄清楚了您要询问的所有内容。在 RAM 中保留多少,如何写入快速、高速率等。
      【解决方案5】:

      首先计算带宽! 5000 条消息/秒,每个 2kb = 10mb/秒。每分钟 - 600mb。好吧,您可以将其放入 RAM 中。然后每小时冲洗一次。

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

      【讨论】:

        【解决方案6】:

        我会同意 Kyle 的观点,并选择像 PI 这样的包装产品。请注意 PI 非常昂贵。

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

        我还建议使用数据库来存储您的数据。不过,您需要将数据批量插入到数据库中,因为我认为您需要一些强大的硬件来允许 SQL 每秒执行 5000 个事务。您最好每在队列中累积 10000 条消息进行一次批量插入。

        数据大小:

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

        50 * 5000 = 244kb/秒 -> 14mb/分钟 -> 858mb/小时

        【讨论】:

        • 每条消息更像是 20 到 30 个字节......所以它并没有你想象的那么糟糕。
        【解决方案7】:

        也许您不想要数据库安装的开销?

        这种情况,你可以试试a filesystem-based database like sqlite

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

        【讨论】:

          【解决方案8】:

          我会制作 2 个单独的程序:一个用于接收传入的请求,对其进行格式化,然后将它们写到一个文件中,另一个用于从该文件中读取并将请求写出。以这种方式做事可以让您最大限度地减少打开的文件句柄的数量,同时仍然实时处理传入的请求。如果您使第一个程序格式正确输出,那么将其处理为单个文件应该很简单。

          【讨论】:

          • 第二个程序如何工作?它会同时打开 1000 个文件吗?这就是为什么我为项目“2”写了“不知何故”。
          • 我会根据需要打开和关闭文件。来自操作系统的资源并不重,但没有一个进程同时消耗 1000 个文件那么重。它可能无法实时处理,但应该远远落后。
          【解决方案9】:

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

          【讨论】:

            【解决方案10】:

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

            它不允许我发布超链接,所以只需用谷歌搜索这 2 个产品,您就会找到有关它们的信息。

            编辑

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

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

            我所说的基本上是衡量购买可靠产品的成本与构建自己的产品的成本。

            【讨论】:

              【解决方案11】:

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

              所有这些确实引出了一个问题:为什么不使用数据库,以及为什么需要 1000 个不同的文件——你可能有一个很好的理由——但话又说回来,也许你应该重新考虑你的策略并确保它是合理的在你走这条路很远之前进行推理。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2014-01-03
                • 2015-03-03
                • 2012-12-25
                • 1970-01-01
                • 2021-03-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多