The Google Guava Cache is used in the project
The target
- Using a cache background
- Technology selection
- Build the Cache using Guava Cache
- Cache test
Using a cache background
The project to access the cache is a transaction processing service that consumes the initial transaction from RocketMQ and processes the transaction according to the business rules; , originally is the user information in the transaction did not check, the transaction data in the shall prevail, but with the increase of trading volume, and third party merchants access to trading in the user data become no longer reliable, in the face of this problem requires user information check, because we are micro service architecture, user information in the center of the user, The most intuitive way is to call the interface of the user center to verify user information when consuming each transaction. However, the transaction volume is very large in peak business hours, which will lead to increased pressure on the user center. In view of this, we introduce cache.
Technology selection
In terms of technology selection, there are no more than two kinds of centralized cache and local cache. The centralized cache can use Redis, memcache, etc. Considering that the system used Redis for transaction processing and its resources were limited, we gave up the centralized cache and chose local cache without considering the introduction of other middleware. Which are not blind to the selection, first volume predictable, and in addition to the timing of the specific volume is relatively smooth, second users and predictable, since the early days of the business has been the user increases the amount of also is very smooth, there is one of the most important reason is that the user of our system has a characteristic, that is hot users, It’s possible that a handful (millions) of people make transactions every day.
Local cache, I list the following implementations
- Custom global
Map
- Guava Cache
I usually use the Map when I use a cold data, because the cold data is configuration data or parameter data, which will not change, so it is predictable when considering expiration and updating cache, and the amount of data is not large and fixed, which is very simple. However, more considerations should be taken into account when caching user data. For example, there is a large amount of user data, cached data is expired, and cached data has the characteristics of hot spots. Therefore, a lot of Cache strategies need to be implemented when customizing a map
As mentioned earlier, our users are called “hot users”, that is, there are only a handful of users who make transactions on a daily basis, so we need to consider the following points when using caching:
- An estimate of the number of users generating transactions
- Cache obsolescence strategy
The purpose of estimating the number of users that generate transactions is to set the size of the cache, because the number of users is actually too large to cache all user data at once; The elimination strategy of cache is aimed at hot users, and the number of active users is estimated to be 100W according to the transaction volume, so I set the size of cache to be 100W and the expiration policy to be LRU (least recently used).
Build the Cache using Guava Cache
@slf4j public final class CacheC {/** * Clear cache capacity * When the configured maximum cache capacity is reached, */ private static final int MAX_NUM = 1000000; /** * @suppressWarnings ("UnstableApiUsage") private static Cache<String, String> Cache; /** * add cache * @param cardNum traffic card number * @Param merchantNo merchant number * @return Merchant number */ @SuppressWarnings("UnstableApiUsage") public static String addCache(String cardNum, String merchantNo) { if (Objects.isNull(CACHE)) { CACHE = CacheBuilder.newBuilder() .maximumSize(MAX_NUM) .concurrencyLevel(8) .build(); } log.info(logutil. marker(cardNum), "Add card number cache "); CACHE.put(cardNum, merchantNo); return merchantNo; } /** * get merchant number from cache * @param cardNum * @return Merchant number */ @suppressWarnings ("UnstableApiUsage") public static String getCache(String cardNum) { if (Objects.isNull(CACHE)) { return null; } String value = CACHE.getIfPresent(cardNum); If (stringutils.isblank (value)) {log.info(logutil.marker (cardNum), "missed cache "); } else {log.info(logutil.marker (value), "hit cache "); } return value; }}Copy the code
Cache test
@RunWith(MockitoJUnitRunner.class) public class CacheCTest {
private static final int count = 10000; @Test public void testCacheC() { for (int i = 0; i < count; i++) { CacheC.addCache(i + "", i + ""); } for (int i = 0; i < count; i++) { String value = CacheC.getCache(1 + ""); If (stringutils.isblank (value)) {system.out.println (" No cache "); } else {system.out.println (" cache "); }}}Copy the code
}
conclusion
Guava Cache is very simple to use, provides implementation of Cache obsolescence policies, and provides some very interesting features such as statistics. In the next article, we’ll look at other features of Guava Cache