Arnab Biswas
Arnab Biswas

Reputation: 4605

In memory read/write cache in Java based on flat file

I have a flat file which consists of a list of device identifiers. When my Java/tomcat based application receives a request from a particular device, it decides the business logic based on presence of the device identifier in the file (The device identifier MAY or MAY NOT be there in the file even though the device exists). Also, there are use cases when

  1. new identifiers needs to be added to the file
  2. identifiers can be removed from the file.

To make the (multi-threaded) application faster, instead of directly accessing the file for every read/write operation, I need to store the content in-memory.

Here are the requirements (summary) :

  1. Read the content of the file in memory (cache) during the application start up.

  2. Read the content from the cache in a multi-threaded manner. If the content is not there in the cache it should not be there in the file and vice versa (Single point of truth).

  3. When there is a new device identity, the cache as well as file needs to updated.

  4. When there is a need to delete a device identity, the cache as well as file needs to updated.

  5. The application runs in Java.

What are the options available? I initially thought of using gauva cache. But, I am not sure if it supports writing it's content back to the source file or not. Even a simple properties file (java.util.properties) should also do. But, not sure if that will be suitable in a highly multi-threaded environment.

Appreciate your suggestions.

Upvotes: 0

Views: 1535

Answers (2)

Ben Manes
Ben Manes

Reputation: 9591

Like most caches, Guava's is designed to be used primarily in a read-through manner. The intent is that the authoritative data source is updated and the cache is then invalidated. The cache does not support write-through or write-behind, and adding those capabilities on top may lead to subtle race conditions.

The Java 8 rewrite, Caffeine, supports adding that functionality through ConcurrentHashMap's atomic compute methods. A write-through uses a compute that updates the data source and, if successful, stores the value in the cache. A write-behind uses a compute method that asynchronously updates the data source and optimistically stores the value in the cache. In both cases, if the entry exists during a compute then the read is non-blocking and receives the old value until the update completes.

Neither write-through nor write-behind are good approaches for common usages of an in-memory caches. When appropriate they require more thoughtful care and customization, so supplying generic support was thought to lead developers astray and provide little benefit. The rewrite provided the opportunity to make the functionality possible, without promoting it directly.

Upvotes: 4

Brett Walker
Brett Walker

Reputation: 3576

As a starting point using the HashSet as an extension point.

 class DeviceCache extends HashSet<Device> {

  boolean add(Device d) {
    boolean rv = super.add(d);

    if (!rv) {
      ... Add the device to the file.
    }

    return rv;
  }

  remove(Device d) {
    boolean rv = super.remove(d);

    if (rv) {
    ... Remove the device from the file
    }

    return fv;
  }
}

It is far from complete. Any thoughts?

Upvotes: 1

Related Questions