偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Guava Cache 異步刷新技巧,你值得擁有!

開發(fā) 前端
Guava Cache 的數(shù)據(jù)結(jié)構(gòu)跟 JDK1.7 的 ConcurrentHashMap 類似,提供了基于時(shí)間、容量、引用三種回收策略,以及自動(dòng)加載、訪問統(tǒng)計(jì)等功能。 圖片

Guava Cache是一款非常優(yōu)秀的本地緩存框架。

這篇文章,我們聊聊如何使用 Guava Cache 異步刷新技巧帶飛系統(tǒng)性能 。

圖片圖片

1 經(jīng)典配置

Guava Cache 的數(shù)據(jù)結(jié)構(gòu)跟 JDK1.7 的 ConcurrentHashMap 類似,提供了基于時(shí)間、容量、引用三種回收策略,以及自動(dòng)加載、訪問統(tǒng)計(jì)等功能。

圖片圖片

首先,我們溫習(xí)下 Gauva Cache 的經(jīng)典配置 。

圖片圖片

例子中,緩存最大容量設(shè)置為 100 (基于容量進(jìn)行回收),配置了失效策略和刷新策略。

  • 失效策略

配置 expireAfterWrite 后,緩存項(xiàng)在被創(chuàng)建或最后一次更新后的指定時(shí)間內(nèi)會過期。

  • 刷新策略

配置 refreshAfterWrite 設(shè)置刷新時(shí)間,當(dāng)緩存項(xiàng)過期的同時(shí)可以重新加載新值 。

這個(gè)例子里,有的同學(xué)可能會有疑問:為什么需要配置刷新策略,只配置失效策略不就可以嗎?

當(dāng)然是可以的,但在高并發(fā)場景下,配置刷新策略會有奇效,接下來,我們會寫一個(gè)測試用例,方便大家理解 Gauva Cache 的線程模型。

2  理解線程模型

我們模擬在多線程場景下,「緩存過期執(zhí)行 load 方法」和「刷新執(zhí)行 reload 方法」兩者的運(yùn)行情況。

圖片圖片

執(zhí)行結(jié)果見下圖:

圖片圖片

執(zhí)行結(jié)果表明:Guava Cache 并沒有后臺任務(wù)線程異步的執(zhí)行 load 或者 reload 方法。

失效策略:expireAfterWrite 允許一個(gè)線程執(zhí)行 load 方法,其他線程阻塞等待 。當(dāng)大量線程用相同的 key 獲取緩存值時(shí),只會有一個(gè)線程進(jìn)入 load 方法,而其他線程則等待,直到緩存值被生成。這樣也就避免了緩存擊穿的危險(xiǎn)。高并發(fā)場景下 ,這樣還是會阻塞大量線程。

刷新策略:refreshAfterWrite 允許一個(gè)線程執(zhí)行 load 方法,其他線程返回舊的值。單個(gè) key 并發(fā)下,使用 refreshAfterWrite ,雖然不會阻塞了,但是如果恰巧同時(shí)多個(gè) key 同時(shí)過期,還是會給數(shù)據(jù)庫造成壓力。

為了提升系統(tǒng)性能,我們可以從如下兩個(gè)方面來優(yōu)化 :

  1. 配置  refresh < expire ,減少大量線程阻塞的概率;
  2. 采用異步刷新的策略,也就是線程異步加載數(shù)據(jù),期間所有請求返回舊的緩存值,防止緩存雪崩。

下圖展示優(yōu)化方案的時(shí)間軸 :

圖片圖片

3 兩種方式實(shí)現(xiàn)異步刷新

3.1 重寫 reload 方法

圖片圖片

3.2 實(shí)現(xiàn) asyncReloading 方法

圖片圖片

不管使用哪種方案, 都需要定義單獨(dú)的線程池來執(zhí)行刷新任務(wù) 。

4 異步刷新 + 多級緩存

2018 年,筆者服務(wù)的一家電商公司需要進(jìn)行 app 首頁接口的性能優(yōu)化。筆者花了大概兩天的時(shí)間完成了整個(gè)方案,采取的是兩級緩存模式,同時(shí)采用了 Guava 的異步刷新機(jī)制。

整體架構(gòu)如下圖所示:

圖片圖片

緩存讀取流程如下 :

  • 業(yè)務(wù)網(wǎng)關(guān)剛啟動(dòng)時(shí),本地緩存沒有數(shù)據(jù),讀取 Redis 緩存,如果 Redis 緩存也沒數(shù)據(jù),則通過 RPC 調(diào)用導(dǎo)購服務(wù)讀取數(shù)據(jù),然后再將數(shù)據(jù)寫入本地緩存和 Redis 中;若 Redis 緩存不為空,則將緩存數(shù)據(jù)寫入本地緩存中。
  • 由于步驟1已經(jīng)對本地緩存預(yù)熱,后續(xù)請求直接讀取本地緩存,返回給用戶端。
  • Guava 配置了 refresh 機(jī)制,每隔一段時(shí)間會調(diào)用自定義 LoadingCache 線程池(5個(gè)最大線程,5個(gè)核心線程)去導(dǎo)購服務(wù)同步數(shù)據(jù)到本地緩存和 Redis 中。

優(yōu)化后,性能表現(xiàn)很好,平均耗時(shí)在 5ms 左右,同時(shí)大幅度的減少應(yīng)用 GC 的頻率。

該方案依然有瑕疵,一天晚上我們發(fā)現(xiàn) app 端首頁顯示的數(shù)據(jù)時(shí)而相同,時(shí)而不同。

也就是說:雖然 LoadingCache 線程一直在調(diào)用接口更新緩存信息,但是各個(gè)服務(wù)器本地緩存中的數(shù)據(jù)并非完成一致。

這說明了兩個(gè)很重要的點(diǎn):

  • 惰性加載仍然可能造成多臺機(jī)器的數(shù)據(jù)不一致;
  • LoadingCache 線程池?cái)?shù)量配置的不太合理,  導(dǎo)致了任務(wù)堆積。

最終,我們的解決方案是:

  • 異步刷新結(jié)合消息機(jī)制來更新緩存數(shù)據(jù),也就是:當(dāng)導(dǎo)購服務(wù)的配置發(fā)生變化時(shí),通知業(yè)務(wù)網(wǎng)關(guān)重新拉取數(shù)據(jù),更新緩存。
  • 適當(dāng)調(diào)大 LoadingCache 的線程池參數(shù),并在線程池埋點(diǎn),監(jiān)控線程池的使用情況,當(dāng)線程繁忙時(shí)能發(fā)出告警,然后動(dòng)態(tài)修改線程池參數(shù)。

5 總結(jié)

Guava Cache 非常強(qiáng)大,它并沒有后臺任務(wù)線程異步的執(zhí)行 load 或者 reload 方法,而是通過請求線程來執(zhí)行相關(guān)操作。

為了提升系統(tǒng)性能,我們可以從如下兩個(gè)方面來處理 :

  • 配置 refresh < expire,減少大量線程阻塞的概率。
  • 采用異步刷新的策略,也就是線程異步加載數(shù)據(jù),期間所有請求返回舊的緩存值。

筆者曾經(jīng)優(yōu)化過某電商網(wǎng)站的首頁接口,使用的方案是:Guava 的異步刷新機(jī)制 + 多級緩存 ,取得了非常好的優(yōu)化效果。

盡管如此,我們在使用這種方式時(shí),依然需要考慮的緩存和數(shù)據(jù)庫一致性問題。

參考資料:

https://albenw.github.io/posts/df42dc84/


責(zé)任編輯:武曉燕 來源: 勇哥Java實(shí)戰(zhàn)
相關(guān)推薦

2021-01-21 09:45:16

Python字符串代碼

2021-03-18 07:52:42

代碼性能技巧開發(fā)

2020-02-03 12:25:35

Python工具服務(wù)器

2021-09-06 10:22:47

匿名對象編程

2023-12-29 08:17:26

Python代碼分析Profile

2024-08-29 08:28:17

2020-12-14 13:32:40

Python進(jìn)度條參數(shù)

2021-07-05 09:40:57

工具Node開源

2020-09-01 07:41:56

macOS工具

2014-12-19 10:55:17

Linux性能監(jiān)控

2024-12-18 16:53:13

ncduLinux磁盤分析

2020-10-09 11:54:33

Vue用戶的React

2022-09-21 08:16:18

緩存框架

2020-06-15 14:43:16

Python開發(fā)工具

2020-03-08 13:24:47

JavaScript開發(fā)

2022-01-18 16:42:03

區(qū)塊鏈加密信息資源

2011-10-08 10:15:29

Web

2013-07-05 16:08:40

開發(fā)效率

2016-07-28 09:37:30

開源協(xié)作軟件Collabtive

2023-09-11 07:46:03

Cache2k緩存
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號