Local cache guava cache tutorial

Time:2021-2-25

1. Background

The main function of cache is to temporarily store the data processing results of business system in memory and wait for the next access. There are many occasions in daily development, some data are not very large, will not be changed frequently, and access is very frequent. However, limited by the performance of hard disk IO or remote network, it may be very time-consuming. Will lead to our program is very slow, which in some business is intolerable! And cache is the artifact to solve this kind of problem!

Caching is widely used in many systems and architectures

  • CPU cache
  • Operating system cache
  • HTTP cache
  • Database cache
  • Static file cache
  • Local cache
  • Distributed cache

It can be said that in the field of computer and network, cache is everywhere. It can be said that as long as the hardware performance is not equal, there will be caching in the places involving network transmission.

There are two kinds of cache: centralized cache and distributed cache

The difference between “centralized cache” and “distributed cache” actually lies in the concept of “centralized” and “non centralized”. Its objects may be servers, memory modules, hard disks, etc.

2.Guava Cache

Google’s guava is a very good project. It provides tools such as collection, cache, concurrency, string, etc. it is really a powerful tool for java development. Let’s talk about the usage of loadingcache.

2.1 easy to use

When using cache, we first read the cache. When the cache does not exist, we get it from the actual data storage, such as dB, disk, network, etc., that is, get if absent compute. Guava provides a cache loader mechanism, which allows us to automatically complete this process by setting the loader. For example:

Cache<String, User> cache = CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES);
user = cache.get(name, () -> {
    User value = query(key);//from databse, disk, etc.
    return value;
});

Or use loadingcache:

LoadingCache<String, User> cache = CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES).build(
     new CacheLoader<String, User>() {
        @Override
        public User load(String name) throws Exception {
        User value = query(key);//from databse, disk, etc.
        return value;
        }
    }
);

This is much more convenient than writing a map to cache data, and you can also set a timeout to automatically help us clean up expired data.

However, it should be noted that cacheloader does not allow the returned data to be null, otherwise it will throw an exception:CacheLoader returned null for key. So we need to ensure that the data we are looking for must exist, or throw an exception for external processing. In some cases, our data may not be available. For example, in the user management module, before adding new data, we need to query whether the original user already exists, so it is not appropriate to throw an exception. At this time, we can use optional to optimize the cacheloader

 LoadingCache<String, Optional<User>> cache = CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES).build(
     new CacheLoader<String, Optional<User>>() {
        @Override
        public Optional<User> load(String name) throws Exception {
        User value = query(key);//from databse, disk, etc.
        return Optional.ofNullable(value);
        }
    }
);

In this way, we ensure that the return value of cacheloader is not null, and we only need to judge whether the business data exists Optional.ifPresent At the same time, other functions of optional are also very useful in business logic.

2.2 comparison with map

Guava cache is similar to concurrent map, but not exactly the same. The basic difference is that concurrent map keeps all added elements until they are explicitly removed. In contrast, in order to limit memory usage, guava cache is usually set to automatically recycle elements. In some scenarios, although loadingcache does not recycle elements, it is also useful because it loads the cache automatically.

Guava cache caches data in memory. Compared with database or redis storage, it is more efficient to access data in memory. According to the introduction on the official website of guava, we can consider using guava cache in the following situations:

  1. Willing to consume some memory space to improve speed.
  2. Some keys are expected to be queried multiple times.
  3. The total amount of data stored in the cache will not exceed the memory capacity.

Therefore, a small amount of data frequently used by the program can be stored in the guava cache to improve the program performance.

2.3 refresh and expire mechanism of guava cache

Take a look at three time-based ways to clean or refresh cached data:

  expireAfterAccess: when a cache item is not read or written within a specified period of time, it is recycled.

  expireAfterWrite:When the cache item is not updated within a specified period of time, it will be recycled.

  refreshAfterWrite:How long will the cache item be refreshed after the last update operation.

The comparison of these three methods can be referred to as follows:Refresh mechanism of guava cache