今天一個接口響應超時,然后我優化,用到了本地緩存。
maven 依賴
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>27.1-jre</version> </dependency>
LocalCache 本地緩存工具類
package com.itbac.common.cache; import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; /** * 本地緩存工具 * * <br/>對於一些改動頻率低且調用非常頻繁,可加上本地有效時間短(1分鍾)的二級緩存 * * @author Bac * * @Date 2020年1月6日 下午12:12:12 */ public class LocalCache<K,V> { /**默認的本地緩存最大數據長度*/ private static final long Default_Maximum_Size = 5_000; /**本地緩存數據長度為1 */ private static final long Single_Size = 1; /**寫入本地緩存后的失效時間秒數*/ private static final long Max_Expire_After_Write = 1 * 60; private Cache<K, Optional<V>> cache; private LocalCache(){} /** * 創建本地緩存對象(創建此對象后,需要用static成員變量進行唯一初始化引用) * (默認為一分鍾緩存) * @return */ public static <K,V> LocalCache<K,V> create() { LocalCache<K,V> local = new LocalCache<K,V> (); local.cache = CacheBuilder.newBuilder() .maximumSize(Default_Maximum_Size) .expireAfterWrite(Max_Expire_After_Write, TimeUnit.SECONDS) .build(); return local; } /** * 創建本地緩存對象 * @param expireAfterWrite 寫入緩存后失效的秒數 * @return */ public static <K,V> LocalCache<K,V> create(long expireAfterWrite) { LocalCache<K,V> local = new LocalCache<K,V> (); local.cache = CacheBuilder.newBuilder() .maximumSize(Default_Maximum_Size) .expireAfterWrite(expireAfterWrite <= 0 ? Max_Expire_After_Write : expireAfterWrite, TimeUnit.SECONDS) .build(); return local; } /** * 創建只能緩存一個數據元素的本地緩存對象 * @return */ public static <K,V> LocalCache<K,V> createSingleSize() { LocalCache<K,V> local = new LocalCache<K,V> (); local.cache = CacheBuilder.newBuilder() .maximumSize(Single_Size) .expireAfterWrite(Max_Expire_After_Write, TimeUnit.SECONDS) .build(); return local; } private Cache<K, Optional<V>> getCache() { return this.cache; } /** * 獲取緩存k對應的值,沒有值返回null * @param k 緩存key * @return */ public Optional<V> get(K k) { return getCache().getIfPresent(k); } /** * 獲取緩存key對應的值,若key未在本地緩存中,使用call進行初始化 * @param k 緩存key * @param call 若key未在本地緩存中,使用call進行初始化。 * 可用Lambada表達式, () ->{ 具體邏輯,return V }; * @return */ public V get(K k,Supplier<V> call) { if (k == null) { return null; } /** * 由於Guava的Callable接口中,若采用過期機制, * 如果自帶的Callable返回了null,get(xx,CallAble)便會拋出異常: CacheLoader returned null for key * 故采用Optional + 額外的Supplier */ Optional<V> value = get(k); //未放置本地緩存數據 if (value == null) { V v = call.get(); getCache().put(k, Optional.ofNullable(v)); return v; } return value.orElse(null); } }
使用本地緩存
package com.itbac.common.cache; import java.util.ArrayList; import java.util.List; public class SkuQueryService { //本地緩存,寫入后20秒失效 private static final LocalCache<String, List<String>> Cache = LocalCache.create(20); public static void main(String[] args) { //使用本地緩存 List<String> list = Cache.get("key", () -> { //具體獲取數據的邏輯 List<String> strings = new ArrayList<>(); strings.add("假裝有數據"); return strings; }); } }
設置緩存后,要等到了時間,緩存才會失效。需要容忍一段時間的數據不一致。