Open source high-performance local cache-Caffeine

High-performance local cache

Before you cache the local cache, you must be thinking, what is good about the local cache, isn't it just a map? Store the data to be cached in the map and you can do it yourself. But here are a few points to consider:

  • Concurrency-use a normal Map or a thread-safe ConcurrentMap?

  • Capacity-How big is the capacity of the map?

  • Expiration Policy-Does the data in the Map need to be cleared regularly if it is not used for a long time?

  • Eviction Policy-What should I do if the data has not expired, but the capacity is full?

If you also have these problems then please see the following article.

Before, I introduced Google’s local cache Guava Cache. If you are interested, you can read this article of mine:

Google’s local cache is really easy to use

But I think this local cache is not very convenient to use, and the performance is not high. Therefore, I recommend a high-performance local caching framework-Caffeine, an upgraded version of Guava Cache, which is very convenient to use. Let's take a look at an example of its use.

performance

Performance display:

Read(100%)

image

Write(100%)

image

From the above picture, we can see: Whether it is reading or writing, how strong is the performance of Caffeine.

Usage example

First import the Maven dependency:

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>2.8.4</version>
</dependency>

Test code:

image

Let's create a cache first cache. Here we define some properties:

maximumSize():Here you can set the upper limit of the number of caches.

expireAfterWriter():Indicates how long it will expire after the last write.

weakKeys():The key uses a weak reference.

weakValues():The value value uses a weak reference to prevent memory leaks.

removeListener():Monitoring when the cache expires.

Regarding weak references and memory leaks, those who are interested can check out this article I wrote:

Do you understand the strengths and weaknesses in Java?

Are you afraid of memory leaks when using ThreadLocal? Then you should take a look at this article

Caffeine uses thread-safe, concurrently high-performance ConcurrentMap

image

We start to get from the cache:

String valueFromCache = cache.get("lvshen", key -> getValue(key));

As the code, from the cacheget key to the lvshenvalue, if the cacheacquisition is less than we would from the method getValue(key)get in. Generally speaking, there are 3 steps to check the cache:

  • Query from the cache, if there is a value in the cache, return

  • If there is no value in the cache, get it from the database and return

  • Store the value in the database in the cache

Caffeine's local cache is also the same logic. In order to simulate this logic, we get lvhsenthe value of key from the cache twice . The first time it is retrieved from the database, the getValue()method will be called , and the second time it will be retrieved directly from the cache.

The results of the operation are as follows:

调用了getValue方法....
测试结果:lvshen
测试结果2:lvshen

The operation results confirmed the above logic.

In addition to automatically clearing the cache, we can also manually clear the cache:

cache.invalidate("lvshen");

The big difference between Guava Cache and Caffeine is the elimination algorithm used, the LRU algorithm used by Guava Cache, and the upgraded TinyLFU algorithm of the LFU algorithm used by Caffeine. As for the difference between the LRU and LFU algorithms, you can read this article I wrote article:

[Technical dry goods] Elimination algorithm LRU and LFU

As an upgraded version of the LFU algorithm, TinyLFU is more powerful in performance (high hit rate, low memory usage). The specific implementation will not be detailed here.

Of course, we can also use SpringBoot:

First configure config

image

Direct injection when used:

@Autowired
Cache<String, Object> caffeineCache;

...
public void fun(String key) {
    caffeineCache.put(key,"I am Lvshen");
}

We can also define it in the form of annotations:

Introduce maven dependency

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

Configure config

image

Use as follows:

@CachePut(key = "#userInfo.id")
public void addUser(User userInfo) {
    //这里模拟存入数据库中
    userMap.put(userInfo.getId(), userInfo);
}

@Cacheable(key = "#id")
public User getByName(Integer id) {
    //先从缓存中获取,缓存中没有,再从数据库中获取
    return userMap.get(id);
}

In this way, we can also realize the integrated use of SpringBoot and Caffeine.

Official document

This article is just an introduction to Caffeine. If you want to learn more about children's shoes, you can check the official documents.

image

Official document

The official documentation of Caffeine is as follows:

(https://github.com/ben-manes/caffeine/wiki/Policy-zh-CN)

Guess you like

Origin blog.csdn.net/wujialv/article/details/113251051