【问题标题】:Recommend a fast & scalable persistent Map - Java推荐一个快速且可扩展的持久化 Map - Java
【发布时间】:2010-12-04 22:47:48
【问题描述】:

我需要一个磁盘支持的 Map 结构才能在 Java 应用程序中使用。它必须具有以下条件:

  1. 能够存储数百万条记录(甚至数十亿条)
  2. 快速查找 - Map 上的大多数操作只是查看键是否已存在。这和上面的 1 是最重要的标准。应该有一个有效的内存缓存机制,用于频繁使用的键。
  3. 持久,但不需要是事务性的,可以忍受一些失败。即乐于定期与磁盘同步,并且不需要事务性。
  4. 能够存储简单的原始类型 - 但我不需要存储序列化对象。
  5. 它不需要分布式,即在一台机器上运行。
  6. 设置简单且免费使用。
  7. 不需要关系查询

记录键将是字符串或长整数。如上所述,读取将比写入频繁得多,并且大多数读取将只是检查密钥是否存在(即不需要读取与密钥相关的数据)。每条记录只更新一次,记录不会被删除。

我目前使用 Bdb JE,但正在寻找其他选择。


更新

通过减少对辅助键的依赖,提高了我现有 BDB 设置的查询性能。有些查询需要连接两个辅助键,通过将它们组合成一个复合键,我在查找中删除了一个间接级别,这可以很好地加快速度。

【问题讨论】:

  • 我正在考虑的一个选项是改变我使用现有 BDB 实现的方式。目前,我的所有记录都有一个大型数据库。但是,我应该能够将数据划分为多个集合,并且每个集合有一个数据库 - 如果我知道在任何时间点我只需要访问某些集合,那么我可以关闭那些我不使用的集合,这应该有助于 bdb 对我更有效地管理数据。
  • 我用过 bdb je。根据您的标准,它非常适合。但是,我对它的脆弱性感到非常失望,并且不建议将其用于生产用途。 java 进程中的任何问题都会导致 bdb 子系统需要重新启动,blech!
  • 我不确定您所说的 BDB JE 的“脆弱性”是什么意思。 BDB JE 可扩展到 TB 级数据,我一直在生产系统中使用它。这是一项很棒的技术。

标签: java map berkeley-db persistent berkeley-db-je


【解决方案1】:

JDBM3 完全符合您的要求。它是一个磁盘支持的地图库,具有非常简单的 API 和高性能。

更新

这个项目现在已经演变成 MapDB http://www.mapdb.org

【讨论】:

    【解决方案2】:

    您可能想查看OrientDB

    【讨论】:

      【解决方案3】:

      您可以从http://openhft.net/products/chronicle-map/ 尝试 Java Chronicles Chronicle Map 是一种高性能、堆外、键值、内存中的持久数据存储。它的工作方式类似于标准的 java 地图

      【讨论】:

      • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
      • @krister - 我认为这是一个不太理想的问题产生的答案违反了 SO 政策的情况(答案很好地回答了这个问题)。在这种情况下,我倾向于反对这个问题。
      • 分布式缓存拓扑中的复制是付费功能
      【解决方案4】:

      我可能会使用本地数据库。比如说Bdb JEHSQLDB。请问这种方法有什么问题吗?您必须有一些理由寻找替代方案。

      响应 cmets: 由于性能问题,我猜你已经在使用 JDBC 来处理这个问题,可能值得尝试 HSQLB 并阅读Memory and Disk Use 上的章节。

      【讨论】:

      • +1 同意。我会使用常规数据库并为需求编写一个不错的 API,以便可以轻松切换后端。
      • 一旦 Bdb 达到可以缓存在内存中的限制,我发现它的速度慢得令人无法接受。这通常发生在插入大约 1 毫米之后。
      • HSQLDB 怎么样?我猜他们都是 JDBC,所以你应该能够在不修改大部分现有代码的情况下插入它。值得一读:hsqldb.org/doc/2.0/guide/…
      • BDB 会在您达到高速缓存的临界点时减慢速度。 BDB 本质上在内存中有一个 BTree,它试图回答一个请求。如果无法响应请求,则 BDB 会从磁盘中分页更多数据。一旦你的工作集大于你的缓存,你就会发现麻烦。有用于监控缓存命中未命中和缓存大小的 JMX 方法:使用它们来调试您的应用程序,并在必要时增加堆并为 BDB 提供更多缓存。
      • HSQLDB 不是也是一个可接受的解决方案。虽然它可以在磁盘上存储大量数据,但在读取时它确实从磁盘中流式传输这些数据。它将整个ResultSet 读入内存,而不是在您遍历它时将其分页。如果您需要走过大部分桌子,这会破坏您的记忆。 BDB 处理得很好。我也相信 h2 数据库 (h2database.com/html/main.html ) 声称可以解决这个问题,尽管我从未使用过它。
      【解决方案5】:

      从今天开始,我会使用MapDB(基于文件/支持同步或异步)或Hazelcast。在后面,您将必须实现自己的持久性,即通过实现 Java 接口由 RDBMS 支持。 OpenHFT Chronicle 可能是另一种选择。我不确定持久性在那里是如何工作的,因为我从未使用过它,但声称拥有它。 OpenHFT 完全在堆外,允许部分更新(原语)对象而无需(反)序列化,这可能会带来性能优势。

      注意:如果由于内存问题需要基于地图磁盘,最简单的选择是 MapDB。 Hazelcast 可以用作缓存(分布式或非分布式),它允许您在时间或大小之后从堆中逐出元素。 OpenHFT 不在堆中,如果您只需要 jvm 重启的持久性,可以考虑。

      【讨论】:

        【解决方案6】:

        我发现Tokyo Cabinet 是一个简单的持久性哈希/映射,并且可以快速设置和使用。

        这个取自the docs的简短示例展示了从持久性地图中保存和检索数据是多么简单:

            // create the object
            HDB hdb = new HDB();
            // open the database
            hdb.open("casket.tch", HDB.OWRITER | HDB.OCREAT);
            // add item 
            hdb.put("foo", "hop");
            hdb.close();
        

        【讨论】:

          【解决方案7】:

          SQLite 做到了这一点。我写了一个从 Java 中使用它的包装器:http://zentus.com/sqlitejdbc

          正如我在评论中提到的,我已经成功地将 SQLite 用于数千兆字节的数据和数亿行的表。如果您正确考虑索引,它会非常快。

          唯一的痛点是 JDBC 接口。与简单的 HashMap 相比,它显得笨重。我经常为特定项目编写一个 JDBC 包装器,这可能会增加很多样板代码。

          【讨论】:

          • 我已经成功地将 SQLite 用于千兆字节的数据和数亿行的表。如果您正确考虑索引,它会非常快。
          【解决方案8】:

          JBoss (tree) Cache 是一个不错的选择。您可以从 JBoss 独立使用它。非常健壮、高效且灵活。

          【讨论】:

            【解决方案9】:

            我认为Hibernate Shards 可以轻松满足您的所有要求。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-07-17
              • 1970-01-01
              • 2018-12-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多