【问题标题】:Memory-mapped files: pros and cons?内存映射文件:优点和缺点?
【发布时间】:2012-01-21 12:39:08
【问题描述】:

我需要在同一台机器上运行的两个 Java 应用程序(两个不同的 JVM)之间共享数据。我确切地说要共享的数据很大(大约 7 GB)。应用程序必须非常快速地访问数据,因为它们必须以非常高的速率回答传入的查询。我不希望应用程序为每个应用程序保留一份数据副本。

我看到一种选择是使用内存映射文件。应用程序 A 从某个地方(比方说数据库)获取数据并将其存储在文件中。然后应用程序 B 可以使用java.nio 访问这些文件。我不确切知道内存映射文件是如何工作的,我只知道数据存储在一个文件中,并且这个文件(或其中的一部分)被映射到内存的一个区域(虚拟内存?)。因此,这两个应用程序可以读写内存中的数据,并且更改会自动(我猜?)提交到文件中。我也不知道文件完全映射到内存中是否有最大大小。

我的第一个问题是,在这种情况下,两个应用程序共享数据有哪些不同的可能性(我的意思是考虑到数据量非常大,并且访问这些数据必须非常快)?我确切地说这个问题与内存映射 I/O 无关,只是想知道解决同一问题的其他方法是什么。

我的第二个问题是使用内存映射文件的优缺点是什么?

谢谢

【问题讨论】:

  • 您能否提供详细信息,您希望如何使用内存映射文件?
  • 我看到问题不在于触发其他程序中的某些操作。如果是这样,为什么不使用通用数据库来共享数据?
  • @Pangea 我有时间访问限制,应用程序必须快速访问数据。
  • “我猜有些解决方案不适合我的情况?”这不是真的。维基百科文章中的所有 IPC 通信技术都适用于您的案例。你选择了许多之一。这篇文章很好地描述了所有这些。目前尚不清楚是什么让您感到困惑,您还需要了解什么。你能扩展或澄清你的问题吗?您能否引用维基百科文章中让您感到困惑或看起来不完整的特定部分?
  • “有很多解决方案,但有些不太符合我的要求”。错误的。文件不慢。他们非常快。您可以快速共享物理文件。套接字也很快,并且可以处理大量数据。共享内存实际上是内存映射文件。其余的都值得研究。你想知道什么?能具体点吗?

标签: java ipc shared-memory memory-mapped-files


【解决方案1】:

我的第一个问题是两个应用程序共享数据的不同可能性是什么?

正如 S.Lott 指出的那样,有很多机制:

我的第二个问题是使用内存映射文件的优缺点是什么?

优点:

  • 非常快——取决于您访问数据的方式,可能会使用zero-copy 机制直接对数据进行操作,而不会影响速度。必须注意以一致的方式更新对象。
  • 应该非常便携——在 Unix 系统上可用大约 25 年(给予或接受),and apparently Windows has mechanisms too

缺点:

  • 单系统共享。如果你想在多台机器上分发你的应用程序,共享内存不是一个很好的选择。 Distributed shared memory systems are available,但他们感觉很像我的思维方式的错误界面。
  • 即使在单个系统上,如果内存位于单个NUMA node 上但需要由多个节点的处理器访问,则与为每个节点提供自己的段相比,节点间请求可能会显着减慢处理速度记忆。
  • 您不能只存储指针——所有内容都必须存储为偏移到基地址,因为内存可能映射到不同进程中的不同位置。我不知道这对 Java 对象意味着什么,尽管大概是某个聪明人尽了最大努力让它对 Java 程序员透明。如果您不使用他们提供的机制,那么您可能必须自己完成这项工作。 (在 Java 中没有实际的 指针,也许这不是很繁重。)
  • 事实证明,始终如一地更新对象非常困难。在消息传递系统中传递immutable objects 通常会导致程序的并发错误更少。 (Erlang 中的并发编程感觉非常自然和直接。imperative languages 中的并发编程倾向于引入大量新的并发控制:semaphoresmutexesspinlocksmonitors)。

【讨论】:

  • 感谢 sarnold 的详细回答。操作系统级别的解决方案和可移植性如何?当您说应用程序级别时,您的意思是它由 JVM 处理并且是可移植的?
  • @MickaelMarrache:“应用程序级别”我的意思是,作为应用程序作者,您必须提供基础设施,无论是运行 RabbitMQ、Linda、Memcached、CORBA 还是 RESTful Web服务。 (它们是否可以在同一个 JVM 中运行完全是另一回事。)所有操作系统级别的服务都是由操作系统提供的——这可能意味着您需要使用extra modules 才能在本机使用它们。
【解决方案2】:

内存映射文件听起来很头疼。一个简单且不易出错的选项是使用具有集群感知缓存的共享数据库。这样一来,只有写入到数据库,而读取可以从缓存中提供。

作为如何在 hibernate 中执行此操作的示例,请参阅 http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html#performance-cache

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多