【问题标题】:Implementing a file based queue实现基于文件的队列
【发布时间】:2011-03-10 09:39:41
【问题描述】:

我有一个内存有界队列,其中多个线程对对象进行排队。通常,队列应该由处理队列中项目的单个读取器线程清空。

但是,队列可能已满。在这种情况下,我想将任何其他项目保留在磁盘上,这些项目将由另一个后台读取器线程处理,该线程扫描目录中的此类文件并处理文件中的条目。我熟悉 Active MQ,但更喜欢更轻量级的解决方案。如果不严格遵循“FIFO”是可以的(因为持久化的条目可能会被乱序处理)。

是否有任何开源解决方案?我没有找到任何东西,但我想我会在自己开始实施之前对这个列表进行 ping 操作以获取建议。

谢谢!

【问题讨论】:

    标签: java queue persistent


    【解决方案1】:

    您可以使用 SQLLite 之类的东西来存储对象。

    【讨论】:

    • 我想到了,但我真的不需要 SQLLite 功能 - 不需要 SQL。
    • @serverman 我知道,你可以把它用作文件存储引擎,然后按时间戳顺序检索。
    • 您好,Romain 同意。我试图不为操作人员添加另一个 SQL 组件,只是为了这个功能。但是是的 - 你是对的,我可以使用 SQLLite。
    • @serverman - 我知道我听起来像一个破纪录,我只是想确保你明白 SQLLite 不是一个需要安装甚至需要 SQL 的 sql db。它实际上只是一个带有 API 的文件。 SQLLite 不需要安装,您只需要 JAR 文件和操作系统上的文件。 sqljet.com 是一个纯 Java 实现(实际上没有 SQL,只是一个低级 API)
    • 是的,我已经检查并运行了它。看起来它是 sqllite 的仅 java 实现 - 所以我关心的是它有多稳定和维护得好?官方的 sqllite 本身似乎是经过很好测试的产品,但我不确定 sqljet。您可能已经猜到我正在使用 Java。在查看 sqljet 之前,我查看了使用 Java 访问 sqllite - 是否有推荐的访问方法 - sqlite.org/cvstrac/wiki?p=SqliteWrappers 似乎列出了很多选项。只有当 sqljet 不是上述问题的选项时,这才是一个问题。再次感谢!
    【解决方案2】:

    看看http://square.github.io/tape/,以及它令人印象深刻的 QueueFile。

    (感谢 Brian McCallister 的“长尾宝库”指点我)。

    【讨论】:

    • 我现在正在查看这个库,虽然 API 非常简单,但它似乎无法处理来自多个进程对同一存储的并发读/写。 OP 可能不需要该功能,但想指出它。 (或者我刚刚遇到了可能会损坏非日志文件系统上的文件的记录问题?)
    • 原始 QueueFile 有一个多线程写入错误。我们发现并解决了这个问题。我已将它(和一些扩展类)作为要点发布:gist.github.com/serranom/496cacd9d9278d1770a1
    • 如果想要一个轻量级的文件支持队列,这似乎是一个更好的解决方案。
    • 如何使用这个库?我只想简单地入队和出队?
    【解决方案3】:

    EHCache 可以溢出到磁盘。它也是高度并发的,虽然你并不真正需要它

    【讨论】:

    • 我会调查的...谢谢!
    【解决方案4】:

    为什么队列是有界的?为什么不使用动态可扩展的数据结构?这似乎比涉及磁盘要简单得多。

    编辑: 如果没有更多上下文,很难回答您的问题。

    您能否解释一下“内存不足”的含义?队列有多大?你有多少内存?

    您使用的是内存很少的嵌入式系统吗?或者队列中有 2 GB 或更多的内容?

    如果其中任何一个为真,那么您真的应该使用像 BTree 这样的“可交换”数据结构。为一个队列实现一个你自己似乎有点矫枉过正。我只会使用像 SQL lite 这样的嵌入式数据库。

    如果我们都不是真的,那么只需使用向量或链表。

    编辑 2: 您可能不需要 BTree 或数据库。您可以只使用链接的页面列表。但又一次, 我不得不问:这有必要吗?

    或者,如果您愿意以非串行方式处理事物,为什么不一直拥有多个读取器线程?

    虽然我不认为你的提议是最终的选择。

    【讨论】:

    • 队列是有界的,所以我们不会耗尽内存。
    • 嗨斯科特,好点。不,它不是嵌入式系统。但是由于活动突然爆发,队列变满的可能性很小。应用程序必须处理这个问题(即使它很少发生)我倾向于 SQLLite,直到现在才听说过:)谢谢!
    • 如果您不在嵌入式系统上,并且队列中的项目数量不是很大,则不需要任何“满”的概念。我猜你在说“完整”,因为你正在使用 am 数组。为什么?别。使用 Vector 或链表。
    • 斯科特,你是对的。在我们的例子中,队列中的项目数量可能非常大,因为队列项目的处理速度比插入队列数据的速度慢。我打算使用 ArrayBlockingQueue。整个讨论假设如果由于活动突然爆发,队列可能会变满——在这种情况下,我需要溢出。
    【解决方案5】:

    您可以嵌入 berkley db java 版本以将队列元素保存在文件中。

    您可以在此处查看工作示例: http://sysgears.com/articles/lightweight-fast-persistent-queue-in-java-using-berkley-db

    希望对你有帮助

    【讨论】:

      【解决方案6】:

      MapDB 提供由磁盘存储或堆外内存支持的并发映射、集合和队列。它是一个快速易用的嵌入式 Java 数据库引擎。

      https://github.com/jankotek/MapDB

      http://www.mapdb.org/

      【讨论】:

        【解决方案7】:

        目前我发现的最高效且对 GC 友好的解决方案是 Chronicle Queue。 它具有极低的写入延迟,几十纳秒的数量级,比 MapDB 或 SQLite 低几个等级。

        【讨论】:

          猜你喜欢
          • 2012-04-30
          • 2021-01-24
          • 2018-11-14
          • 2021-12-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-03
          相关资源
          最近更新 更多