简体   繁体   中英

Spring Boot: Design a service that caches timed data

I am developing a service using Spring Boot (with Java) and I have the following requirement: The service (when invoked) must generate a timed UUID associated with a string that I pass as input to the service. For example, if I invoke the service like this (with a Http GET):

http://localhost:8080/myService?param=example

The service returns me a UUID like 55bcbfce-8984-4f1d-8435-f9548baf8cb5. The fact is that I want to implement a caching system that stores (for a limited time, like 5 seconds) this UUID along with the passed string example .

So, a "table" stored in the application would be such a thing like this:

UUID param duration
55bcbfce-8984-4f1d-8435-f9548baf8cb5 example 3sec
07ef2e6e-e6a1-45e7-b6a6-51dfab49f782 example2 2sec

Like this, a second service I call by passing it a UUID as input, like this:

http://localhost:8080/mySecondService?UUID=55bcbfce-8984-4f1d-8435-f9548baf8cb5

It could return me ( if invoked in the right time ) the param associated with the UUID 55bcbfce-8984-4f1d-8435-f9548baf8cb5, that is example . If the time is up, then the second service returns an error.

My question is: is there an easy way to implement this WITHOUT USING A DB , but using just a small caching system (the memory will be shared between the two services?), I am new to both Spring Boot and caching. and have never used cache before. I simply cannot use a DB in this situation.

I suppose you have a DTO like this:

public record ResultDTO(String param, int seconds) {
}

You can use @Cacheable annotation that handles automatically the cache by configuring a CacheManager . You can follow this tutorial . At the end the method will something like this:

@Cacheable("params")
public ResultDTO getByUUID(String UUID) {
    // your logic to retrieve the object
}

The code inside getByUUID is executed if the element having UUID input is not in the cache.

You can use a in memory cache implementation. A cache stores some data temporarily and typically has a feature that automatically removes data (expires) after some time duration.

Here is an example with cache2k :

    Cache<String, String> cache =
      Cache2kBuilder.of(String.class, String.class)
        .entryCapacity(5000)
        .expireAfterWrite(5, TimeUnit.SECONDS)
        .build();

    String myService(String param) {
      String uuid = generateUuid();
      cache.put(uuid, param);
    }

    String mySecondService(String uuid) {
      String param = cache.get(uuid);
      if (param == null) {
          // error
      }
      return param;
    }

With the code above the expiry is not happening exactly after 5 seconds but may lag around a second depending on system activity. If you want the item to be visible no more than 5 seconds, use this instead of expireAfterWrite :

  .expiryPolicy((key, value, startTime, currentEntry) ->
    Expiry.toSharpTime(startTime + TimeUnit.SECONDS.toMillis(5)))

Make sure to make the entry capacity high enough, because otherwise the cache will evict data was not used recently.

Do not use @Cacheable of Spring. It would only fit for mySecondService and not for the population of the cache. So don't mix different API concepts.

The approach is basically the same with other cache implementations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM