成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java開發利器之Guava Cache

開發 前端
Guava Cache是一個相對比較簡單并且容易理解的本地緩存框架,今天主要以此為開端來認識并學習如何使用緩存.

前言

緩存技術被認為是減輕服務器負載、降低網絡擁塞、增強Web可擴展性的有效途徑之一,其基本思想是利用客戶訪問的時間局部性(Temproral Locality)原理, 將客戶訪問過的內容在Cache中存放一個副本,當該內容下次被訪問時,不必連接到駐留網站,而是由Cache中保留的副本提供。

在企業Web應用中,通過緩存技術能夠提高請求的響應速度;減少系統IO開銷;降低系統數據讀寫壓力...

緩存的意義

首先我們要知道,在我們開發過程中,為什么要使用緩存,緩存能夠為我們帶來哪些好處!

優點

  • 通過緩存承載系統壓力,減少對系統或網絡資源訪問而引起的性能消耗,在流量較大時能夠很好地減少系統擁塞。
  • 緩存一般都是使用存取非常快的組件實現,通過緩存能夠快速響應客戶端請求,從而降低客戶訪問延遲,提審系統響應速度。
  • 在配備負載均衡的應用架構中,通過緩存靜態資源能夠有效減少服務器負載壓力。
  • 當下游應用故障時,通過返回緩存數據能夠在一定程度上增強應用容錯性。

缺點

  • 緩存數據與實際數據不一致問題問題。
  • 高并發場景時存在緩存擊穿、緩存穿透、緩存雪崩等問題。

總的來說,緩存主要是針對高頻訪問但低頻更新的數據,從而加快服務器響應與原資源訪問壓力。

Guava Cache是一個相對比較簡單并且容易理解的本地緩存框架,今天主要以此為開端來認識并學習如何使用緩存。

Guava Cache特色

本地緩存我們可以簡單的理解為Map,將數據保存到Map(內存)中,下次使用該數據時,通過key直接從Map中取即可。但是使用Map會有一些幾個問題需要考慮:

  • 緩存的容量。不可能無限制的對數據進行緩存,當數據較大時占用系統資源會導致主業務受影響。
  • 緩存的清理。有些緩存使用頻率很低,如果一直占用資源也是一種浪費。
  • 并發訪問時的效率問題。緩存更新時瞬時對系統、網絡資源的訪問導致故障。
  • 緩存使用情況評估

當然以上問題我們通過我們對Map包裝下即可實現,當然Guava Cache也就是基于這種思想,底層原理則是基于Map實現,我們看下其有哪些特色:

  • 緩存過期和淘汰機制

通過設置Key的過期時間,包括訪問過期和創建過期;設置緩存容量大小,采用LRU的方式,選擇最近最久的緩存進行刪除。

  • 并發處理能力

Cache主要基于CurrentHashMap實現線程安全;通過對key的計算,基于分段鎖,提高緩存讀寫效率,降低鎖的粒度,提升并發能力。

  • 更新鎖定

在緩存中查詢某個key,如果不存在,則查源數據,并回填緩存。在高并發下會出現,多次查詢元數據并重復回填緩存,可能會造成系統故障,最明顯的DB服務器宕機,性能下降等。GuavaCache通過在CacheLoader調用load方法時,對同一個key同一時刻只會有一個請求去讀源數據并回填緩存,后面的請求則直接繼續從緩存讀取,有效阻斷并發請求對資源服務的影響。

  • 集成數據源

一般我們在業務中操作緩存,都會操作緩存和數據源兩部分GuavaCache的get可以集成數據源,在從緩存中讀取不到時可以從數據源中讀取數據并回填緩存。

  • 監控統計

監控緩存加載次數、命中率、失誤率以及數據加載時長等。

API介紹

  • 緩存構建

ManualCache此時Cache相當于一個Map,對數據進行CRUD操作時,需要同步操作緩存Map; 高并發情況時,可以使用get(k,loader)讀緩存,通過Cache鎖機制,防止對系統資源(DB)的并發訪問 通過put方法實現緩存的存入與更新;

  • LoadingCache

此時構建的是一個實現了Cache接口的LoadingCache,相比ManualCache,提供了緩存回填機制,即當緩存不存在時,會基于CacheLoader查詢數據并將結果回填到緩存, 在高并發時,可以有效地基于緩存鎖減少對系統資源的調用。此時僅需要關注緩存的使用,緩存的更新與存入都是基于CacheLoader實現;

  • 緩存獲取

get(k)

根據key查詢,沒有則觸發load;如果load為空則拋出異常。

getUnchecked(k)

緩存不存在或返回為null會拋出檢查異常。

get(k,loader)

根據key查詢,沒有則調用loader方法,且對結果緩存;如果loader返回null則拋出異常,此時不會調用默認的load方法。

getIfPresent(k)

有緩存則返回,否則返回null,不會觸發load。

  • 緩存更新

put(k,v)

如果緩存已經存在,則會先進行一次刪除。

  • 緩存刪除

invalidate(k)

根據key使緩存失效。

過期

通過配置的過期參數,比如expireAfterAccess、expireAfterWrite、refreshAfterWrite。

過載

當緩存數據量超過設置的最大值時,根據LRU算法進行刪除。

引用

構建緩存時將鍵值設置為弱引用、軟引用,基于GC機制來清理緩存。

  • 統計

hitRate()

緩存命中率;

hitMiss()

緩存失誤率;

loadCount() 加載次數;

averageLoadPenalty()

加載新值的平均時間,單位為納秒;

evictionCount() 緩存項被回收的總數,不包括顯式清除。

Builder配置

配置

描述

expireAfterAccess

多久沒有讀寫則過期

expireAfterWrite

寫入后多久沒更新自動過期,先刪除,后load

refreshAfterWrite

上一次更新后多久自動刷新,先reload后刪除,并發時會取到老的數據

removalListener

設置緩存刪除監聽

initialCapacity

緩存初始化大小

concurrencyLevel

最大的并發數,可以理解為并發線程數量

maximumSize

最大緩存數量,超過時會根據策略清除

maximumWeight

最大權重容量數,僅用于確定緩存是否超過容量

recordStats

緩存命中統計

簡單示例

  • ManualCache模式

下面以用戶服務為例,我們看下如何在增刪改查方法中使用緩存:

private Cache<String, User> cache = CacheBuilder.newBuilder()
.expireAfterWrite(3, TimeUnit.SECONDS)//寫入多久沒更新自動過期,先刪除,后load
.removalListener(new RemovalListener<Object, Object>() {
@Override
public void onRemoval(RemovalNotification<Object, Object> notification) {
LOGGER.info("{} remove {}",LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),notification.getKey());
}
})
.initialCapacity(20) //初始化容量
.concurrencyLevel(10) // 并發
.maximumSize(100) //最多緩存數量
.recordStats() // 開啟統計
.build();

@Override
public User getUser(String id){
// 緩存不存在時,通過LocalCache鎖機制,防止對數據庫的高頻訪問
User user;
try {
user = cache.get(id,()-> {
LOGGER.info("緩存不存在,從loader加載數據");
return userDao.get(id);
});
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
return user;
}

@Override
public User saveOrUpdateUser(User user){
userDao.saveOrUpdate(user);
cache.put(user.getId(),user);
return user;
}

@Override
public void removeUser(String id){
userDao.remove(id);
cache.invalidate(id);
}
  • LoadingCache模式
private LoadingCache<String, User> cache = CacheBuilder.newBuilder()
// 省略
.build(new CacheLoader<String, User>() {
@Override
public User load(String key) throws Exception {
LOGGER.info("{} load {}",LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),key);
return userDao.get(key);
}

@Override
public ListenableFuture<User> reload(String key, User oldUser) throws Exception {
LOGGER.info("{} reload {}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),key);
ListenableFutureTask<User> listenableFutureTask = ListenableFutureTask.create(() -> userDao.get(key));
CompletableFuture.runAsync(listenableFutureTask);
return listenableFutureTask;
}
});

@SneakyThrows
@Override
public User getUser(String id){
// 緩存不存在或返回為null會拋出異常
try {
return cache.getUnchecked(id);
} catch (Exception e) {
return null;
}
}

@Override
public User saveOrUpdateUser(User user){
cache.invalidate(user.getId());
return userDao.saveOrUpdate(user);
}

@Override
public void removeUser(String id){
cache.invalidate(id);
userDao.remove(id);
}

總結:第一種寫法更像是前面說到的Map,在對數據進行CRUD操作時,需要用戶手動對緩存進行同步的更新或刪除操作,所以叫ManualCache(手動),當然Guava Cache對Map的加強依然有效,比如過期清除,緩存容量限制。第二種方式寫法差不多,主要是引入了CacheLoader接口,在讀數據時緩存數據不存在時,通過CacheLoader的load方法先寫緩存后返回數據。

注意

  • expireAfterWrite、refreshAfterWrite的區別。

在refreshAfterWrite導致緩存失效時,并不會因為更新緩存而阻塞緩存數據的返回,只不過是返回老的數據。

  • 不能緩存null

有時候為了將值為null的數據統一緩存,這樣就不會因為沒有緩存數據而訪問數據庫造成壓力。

  • 讀寫時才進行刪除

Guava Cache的緩存數據刪除是在更新或寫入時才會觸發,沒有單獨的調度服務完成這一工作。

  • 本地緩存

類似的本地緩存還有,有興趣的可以自己嘗試,其實實現思想應該也差不多。

責任編輯:武曉燕 來源: Java技術指北
相關推薦

2024-08-29 08:28:17

2023-09-11 07:46:03

Cache2k緩存

2024-01-04 08:33:11

異步JDK數據結構

2023-02-15 14:02:52

HutoolMapProxy工具包

2022-08-05 12:05:07

JavaGuava集合

2023-09-07 14:04:58

計算機CPU內存

2023-08-02 09:28:28

計算機性能CPU

2025-05-30 07:10:19

2023-07-19 12:24:48

C++constexpr?語句

2017-10-12 12:24:50

java

2012-06-25 17:21:15

天天記事

2011-11-14 09:17:14

Linux運維ClusterShel

2013-07-22 14:15:17

iOS開發ASIHTTPRequ

2021-03-11 00:05:55

Java高并發編程

2021-03-18 00:14:29

JavaCyclicBarri高并發

2021-03-04 07:24:24

JavaSemaphore高并發

2021-12-09 06:59:24

FlinkSQL 開發

2021-08-30 10:19:05

PyFlink 開發環境Zeppelin No

2025-05-16 08:53:06

2019-05-30 09:00:00

微服務系統測試擋板實戰
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 天堂一区二区三区 | 国产精品无码专区在线观看 | 一区二区视频在线 | 97久久精品午夜一区二区 | 国产成人久久 | 欧美成人一区二区 | 在线观看中文字幕 | 成人精品国产一区二区4080 | 免费看a| 中文字幕在线欧美 | 96国产精品久久久久aⅴ四区 | 国内精品视频免费观看 | 国产一区二区在线免费 | 国产精品久久久亚洲 | 欧美亚洲在线 | 中文字幕日韩一区 | 日本公妇乱淫xxxⅹ 国产在线不卡 | 亚洲一区二区三区在线播放 | 性做久久久久久免费观看欧美 | 欧美综合一区二区三区 | 色女人天堂 | 一区二区三区中文字幕 | 欧美一区二区三区在线观看 | 婷婷综合久久 | 国产精品一区二区免费看 | 日韩超碰 | 日韩欧美精品一区 | 成人精品久久 | 欧美视频免费在线观看 | 在线成人av | 精品婷婷 | 亚洲精品成人 | 国产精品毛片一区二区三区 | 欧美精品久久久久 | 国产精品一区二 | 国产精品成人国产乱一区 | 国产在线精品一区二区三区 | 色综合色综合色综合 | 亚洲视频自拍 | 国产精品久久久久久久久大全 | 天天爽夜夜操 |