SpringBoot Cache Caffeine Usage Resolution

  • 2021-11-14 05:48:25
  • OfStack

Directory Redis and Caffeine Difference Similarities and Differences Contact Spring Boot Cache Caffeine Use 1. Need to add dependencies 2. Configuration 3. Use Caffeine Cache Caffeine Other Commonly Used Notes Manually Add, Get, Remove Cache 1. Get data from cache 2. Add data to cache 3. Remove data from cache

Differences between Redis and Caffeine

Similarity

Both are cached ways

Differences

redis is a distributed cache that stores data into the memory of the redis server over the network caffeine is to store data in local applications Compared with redis, caffeine has no consumption on network IO

Contact

1, the two are combined to form a 12-level cache. The usage process is roughly as follows: First, look for data in level 1 cache (caffeine-local application), If not, look for data in level 2 cache (redis-memory). No more, go to the database to find data (database-disk)

Spring Boot Cache Caffeine Use

1. Dependencies to add


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>2.8.6</version>
        </dependency>

2. Configuration

Configure Caffeine in SpringBoot to control cache behavior (such as expiration time, cache size limit, etc.)


import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
@Configuration
@EnableCaching // Turn on the cache 
public class CaffeinConfig {
    @Bean
    // Configure Caffeine Cache behavior (such as expiration, cache size limit, etc.) 
    public Caffeine caffeineConfig() {
        Caffeine caffeine = Caffeine.newBuilder()
                .expireAfterWrite(60, TimeUnit.MINUTES)
                .maximumSize(1000);
        return caffeine;
    }
    @Bean
    public CacheManager cacheManager(Caffeine caffeine) {
        CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
        caffeineCacheManager.setCaffeine(caffeine);
        return caffeineCacheManager;
    }
}

Caffeine configuration instructions:

initialCapacity=[integer] Initial cache space size

maximumSize=[long] Maximum number of caches

maximumWeight=[long] Maximum weight of cache

expireAfterAccess=[duration] Expired by a fixed time after the last write or access

expireAfterWrite=[duration] Expired by a fixed time after the last write

refreshAfterWrite=[duration] Refresh the cache at fixed intervals after creating the cache or last updating the cache

recordStats : Develop statistical functions

Note:

When expireAfterWrite and expireAfterAccess exist at the same time, expireAfterWrite shall prevail.

maximumSize and maximumWeight cannot be used together

3. Use the Caffeine cache

Example 1:

Annotate on the method with @ Cacheable (cacheNames = "xxx") or @ Cacheable (value = "xxx").


 @Cacheable(value = "caffeinSet_Value")
    public String caffeinSetValue(Integer number) {
        String str = number % 2 == 0 ? number + " Is an even number " : number + " Is an odd number ";
        return str;
    }

caffeinSetValue, caffeinSet_Value cache according to the incoming number to find whether there is a matching cache, if there is a direct return results; If not, execute the method, add the result to the cache after execution, and return directly if it matches next time.

Example 2:

When there are multiple parameters, key can be used in the @ Cacheable annotation to select parameters to determine whether the cache exists. You can use condition for conditional filtering, and only those that meet the criteria will be added to the cache.


    /**
     * number Is even, and the cached key Is incoming number Value 
     */
    @Cacheable(value = "caffeinSet_Value", key = "#number", condition = "#number%2==0")
    public String caffeinSetValue(Integer number,String st) {
        String str = number % 2 == 0 ? number + " Is an even number " : number + " Is an odd number ";
        return str+st;
    }

Note: If the parameter number is 2, first judge whether key is 2 in the caffeinSet_Value cache, and then directly return the result. If not, the method is executed, because satisfying the conditions of condition will eventually add the result to the cache.

If the parameter number passed in is odd, the method is executed every time, because condition is not met and will not be added to the cache.

Example 3:


 @Cacheable(value = "caffeinSet_Value", key = "#student.name", condition = "#student.age>10")
    public Student caffeinSetValue(Student student,Integer number) {
        System.out.println(11111);
        return student;
    }

According to student object name to caffeinSetValue cache search. The results are cached only if the age in the student object is greater than 10.

Note:

One method A is tuned to another method B with cache annotation in one class, so it is not cached.

For example, if invalidCache calls caffeinSetValue in the same CaffeinConsumer class, cache is not taken, and cache is not effective;


@Service
public class CaffeinConsumer {
    public String invalidCache(Integer number,String st) {
        String str = caffeinSetValue(number,st);
        return str;
    }
    
    /**
     * number Is even, and the cached key Is incoming number Value 
     */
    @Cacheable(value = "caffeinSet_Value", key = "#number", condition = "#number%2==0")
    public String caffeinSetValue(Integer number,String st) {
        String str = number % 2 == 0 ? number + " Is an even number " : number + " Is an odd number ";
        return str+st;
    }
}

Solution:

1. Take the CacheManger object of Ehcache directly without annotation, and put the data to be cached in it, similar to using Map, and the cache logic is controlled by itself; Or you can use the cache method of redis to add cache;

2. Place method A and method B in two different classes. For example, if both methods are in the same service interface, place method B in another service, so that you can use the cache of B method by tuning B method in A method.

Caffeine Other Commonly Used Notes

1. @ CachePut:

The method annotated with @ CachePut does not check whether the results of previous execution exist in the cache before execution, but executes the method every time and stores the execution results in the specified cache in the form of key-value pairs.

2. @ CacheEvict:

@ CacheEvict is used to annotate on methods or classes that need to clear cached elements. When the tag is on a class, it means that the execution of all the methods in it will trigger the cache clearing operation.

The @ CacheEvict properties you can specify are value, key, condition, allEntries, and beforeInvocation. The semantics of value, key and condition are similar to the corresponding attributes of @ Cacheable.

That is, value indicates which Cache (corresponding to the name of Cache) the cleanup operation occurs on; key indicates which key needs to be cleared. If it is not specified, key generated by default policy will be used; condition represents the condition under which the cleanup operation occurs. If you want to clear all caches, you can use the attribute allEntries=true

Manually add, get and delete caches

The above examples use annotations to cache operations, and sometimes we need to add, delete and modify the cache operations in one method:

1. Get data from the cache

Suppose the key added to the cache named "caffeinSet_Value" in example 2 above is 8 and the value is "8 is even! ! ".

Get this cache manually below:


    @Autowired
    CacheManager cacheManager;
 public String caffeinGetValue() {
        Cache cache = cacheManager.getCache("caffeinSet_Value");
        // Gets the cache name. name For caffeinSetValue
        String name = cache.getName();
        // Get caffeinSetValue Built in the cache is 8 Cache of 
        Cache.ValueWrapper value = cache.get(8);
        String str ="";
        if (null != value) {
            // Gets the value, 8 Is an even number !!
             str = String.valueOf(value.get());
        }
        return str;
    }

2. Add data to the cache


    @Autowired
    CacheManager cacheManager;
    public String caffeinPutValue() {
        Cache cache = cacheManager.getCache("caffeinSet_Value");
        // Gets the cache name. name For caffeinSetValue
        String name = cache.getName();
        /*
        // To the cache put Data. If it doesn't exist key Yes 20 Will join 
  cache.putIfAbsent(number, " Add a test ");
  */
        // To the cache put Data. If it exists key Yes 20 Overwrites the original data 
        cache.put(20,"20 It's even! ! ");
        return " Success ";
    }

3. Delete data from the cache

Delete a cache in the caffeinSet_Value cache:


    @Autowired
    CacheManager cacheManager;
 public String caffeinDeleteValue() {
        Cache cache = cacheManager.getCache("caffeinSet_Value");
        // Gets the cache name. name For caffeinSetValue
        String name = cache.getName();
        // Only 20 This data will be deleted only if it exists 
        boolean bo = cache.evictIfPresent(20);
        return String.valueOf(bo);
    }

Delete all caches in the caffeinSet_Value cache:


    @Autowired
    CacheManager cacheManager;
 public String caffeinDeleteAllValue() {
        Cache cache = cacheManager.getCache("caffeinSet_Value");
        // Gets the cache name. name For caffeinSetValue
        String name = cache.getName();
        // Delete caffeinSet_Value All caches in 
        boolean bo = cache.invalidate();
        return String.valueOf(bo);
    }

Related articles: