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:
“ ”
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%)
Write(100%)
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:
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:
“ ”
“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
We start to get from the cache:
String valueFromCache = cache.get("lvshen", key -> getValue(key));
As the code, from the cache
get key to the lvshen
value, if the cache
acquisition 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 lvhsen
the 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:
“ ”
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
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
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.
Official document
The official documentation of Caffeine is as follows:
“(https://github.com/ben-manes/caffeine/wiki/Policy-zh-CN)
”