1

I need an implementation of java.util.Map that can be shared between different JVMs on different hosts. All the hosts (and thereby the JVMs) have access to the same shared filesystem, so I need something like this:

Map<String,String> sharedMap = new SharedMapInFile("/shared/mymap.map");

I have taken a look at MapDB (http://www.mapdb.org/), but there is no support for sharing between different JVMs (see: https://groups.google.com/forum/#!topic/mapdb/VKVy84MZJko).

Any ideas? TIA!

t777
  • 3,099
  • 8
  • 35
  • 53

2 Answers2

1

Chronicle Map could do that, if your shared filesystem could leverage mapping files into memory on the OS level. E. g:

Map<String, String> sharedMap = ChronicleMap
    .of(String.class, String.class)
    .averageKey(...).averageValue(...)
    .entries(...)
    .createPersistedTo(new File("/shared/mymap.map"));

It might be convenient but pretty inefficient, however, because 3 pages, 12k bytes needs to be send over network on each Map.put() operation. Also, beware that the latency between putting an entry into the map on one host and being able to read that entry on another host could be high, if OS doesn't write the mapped memory back to file system on the writer host for long time. See /proc/sys/vm/dirty_expire_centisecs in Linux.

So setting up direct network connection between the hosts (e. g. using Netty) and sending just keys and values could be much more efficient, though a less convenient solution.

leventov
  • 14,760
  • 11
  • 69
  • 98
0

You can achieve this by using a database as your 'map'. It performs the functionality of a shared map and does so very efficiently. If needed you can easily create a wrapper that implements the 'Map' interface so that it can used just like a HashMap (if something like that is needed).

Sqlite is nice for this because it creates a simple file that you can access if you are on a shared file system (but be aware that it doesn't handle concurrency issues so well). Any other database such as MySQL or Postgres can accomplish this as well (and with better concurrency). Here is an example using Sqlite:

Class.forName("org.sqlite.JDBC");
String connectTo = "jdbc:sqlite:"+myDbName; //filename goes here
java.sql.Connection conn = DriverManager.getConnection(connectTo);

Statement st = conn.createStatement()
ResultSet result = st.executeQuery("select value from tablename where key='myKey'"); //ie some sql statement that gets what you need
result.getString(1);
and so on...
Oscar
  • 334
  • 1
  • 10
  • The contents of this map will not be in any JVM. This therefore does not answer the question. – Joe C Mar 08 '17 at 23:05
  • I disagree. I have often done this. If you wrapper the calls in a map interface it does exactly what the OP is requesting – Oscar Mar 08 '17 at 23:09
  • Thanks for your answer. In common this may be an alternative. In my special case it is not. Because my application have a database, which I can not use for that purpose. – t777 Mar 09 '17 at 12:45