【问题标题】:300 million items in a Map地图中有 3 亿个项目
【发布时间】:2013-01-26 16:29:13
【问题描述】:
  1. 如果他们每个人都保证有一个唯一的密钥(生成和 由外部键控系统强制执行),其中 Map 实现是 适合我吗?假设这必须针对 仅并发查找(数据在 应用程序启动)。
  2. 这 3 亿个唯一键是否有正负 对分桶/碰撞的影响?
  3. 还有其他建议吗?

我的地图看起来像这样

Map<String, <boolean, boolean, boolean, boolean>>

【问题讨论】:

  • 只是一个问题:您确定要在内存中的 Map 中存储 300M 这样的项目吗?如果是简单的 Map,你已经需要 2.4G 的内存来保存 300M 这样的项目了。
  • 如果每秒查找的次数不是太多并且您不想要很高的吞吐量;我会推荐你​​尝试 NoSQL 来解决内存问题;并会给出合理的表现。
  • @Dan 我不确定 300M 如何等同于 2.5 GB 内存。我使用 SizeOf 实用程序测量了 1000 万个数据点(整数键和一个包含四个布尔值作为值的对象)的地图大小,结果约为 1 GB。
  • 你有多少内存,你打算拥有多大的堆?
  • @Pangea:如果 1000 万个条目需要一个演出,那么 300M 条目需要 30GB,对吧?

标签: java hash map hashmap


【解决方案1】:

我不会使用地图,这需要很多内存。特别是在你的情况下。 将值存储在一个数据数组中,并将键存储在排序索引数组中。 在排序后的数组中,您使用 binSearch 来查找键在 data[] 中的位置。

棘手的部分是构建数组,而不会耗尽内存。

你不需要考虑并发,因为你只从数据中读取

进一步尽量避免使用字符串作为键。尝试将它们转换为长。
此解决方案的优点:保证搜索时间不超过 log n。即使在最坏的情况下,当键对哈希码产生问题时

【讨论】:

  • 将值存储在数组中如何显着减少内存占用?
  • 整数数组比对象数组更有效。
  • 因为java中的对象至少需要12个字节。
  • @AlexWien 整数数组 not 怎么可能更高效?如果数据只是四个布尔值,它甚至可以是一个字节数组,一个位掩码就足够了。
  • @AlexWien 我的密钥采用字符串形式。我无法更改这一点,因为我有外部系统分配的密钥。有没有办法将字符串键转换为 int?可能正在使用 hashCode() 但我可能会遇到冲突。
【解决方案2】:

其他建议?你打赌。

使用适当的键值存储,Redis 是第一个想到的选项。当然,这是一个独立的过程和依赖关系,但在适当的系统设计方面,您会赢得很多时间。

应该有一个非常充分的理由说明您希望将业务逻辑与同一进程内存中的多个数据结合起来,即使它是短暂的。我已经尝试了几次,但总是被证明是错误的。

【讨论】:

  • @Already 考虑过这一点,但网络延迟 + 非编组时间可能是问题所在。否则我会使用内存表将所有这些存储在数据库本身中。
  • 在同一台机器上部署进程,您甚至不会使用 tcp 套接字,而是使用 unix 套接字,开销很小甚至不存在。再一次,在可维护性和可扩展性方面取得了巨大的胜利。如果我是你的系统架构师,你必须非常努力地让我相信性能改进是值得的。
  • 但是我有这个应用程序在集群中运行,因此我需要在每台机器上运行 redis。
  • 还有一个很好的理由说明您需要一个合适的数据存储。就像我说的那样,我对这种情况有直接的经验,尝试在内存中实现,但惨遭失败。当然,最初的性能很好,但规模问题很快让我们退缩了。
  • 但是为什么 Redis 在 RDBMS 的内存表之上?
【解决方案3】:

在我看来,您可以简单地使用TreeMap,因为由于它的排序结构,它会给您O(log(n)) 进行数据搜索。此外,它是合格的方法,因为正如您所说,所有数据都将在启动时加载。

【讨论】:

  • 需要大量内存,每个节点都需要左右和平衡信息
  • @AlexWien 我不认为 300_000_000 个字符串 + boolean[4] 太多了。现代服务器有 64..256 GB 的 RAM。 Java x64 没问题。
  • @AlexWien BTW,您使用data[] 的方法非常好。我也会在常见情况下使用这种方法。但在某些情况下,您强烈需要Map 结构。
  • 我在一家 IT 公司工作,但 64GB 只有一台服务器(我知道),并且在这台服务器上运行了大量的虚拟化服务器。所以你会为一个应用程序拥有巨大的内存。看看你是否认识有 64 GB 可用于一个应用程序的人。
  • @AlexWien 是的,我知道有人拥有 96 GB RAM 服务器,只是为了开发单个 Java 应用程序。此外,对于严肃的 IT 公司来说,成本约为 10,000 美元的服务器不是问题。
【解决方案4】:

如果您需要将所有内容保存在内存中,那么您将需要使用一些旨在与这些数量的元素一起使用的库,例如 Huge collections。最重要的是,如果写入的数量会很大,那么您还必须考虑一些更复杂的解决方案,例如Non-blocking hash map

【讨论】:

    猜你喜欢
    • 2013-11-22
    • 2015-07-20
    • 2017-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-23
    • 2011-05-04
    • 1970-01-01
    相关资源
    最近更新 更多