99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

盤點那些強(qiáng)大又低調(diào)的Java緩存

jf_ro2CN3Fa ? 來源:勇哥java實戰(zhàn)分享 ? 2023-11-14 18:02 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

這篇文章,筆者想聊聊那些在業(yè)務(wù)系統(tǒng)中較少被使用,但卻活躍于中間件或者框架里,強(qiáng)大卻又低調(diào)的緩存,筆者愿稱他們?yōu)榫彺媸澜绲膾叩厣?/p>

88a477a0-82d4-11ee-939d-92fbcf53809c.png

1 HashMap/ConcurrentHashMap 配置緩存

HashMap 是一種基于哈希表的集合類,它提供了快速的插入、查找和刪除操作。

HashMap 是很多程序員接觸的第一種緩存 , 因為現(xiàn)實業(yè)務(wù)場景里,我們可能需要給緩存添加緩存統(tǒng)計、過期失效、淘汰策略等功能,HashMap 的功能就顯得孱弱 ,所以 HashMap 在業(yè)務(wù)系統(tǒng)中使用得并不算多。

但 HashMap 在中間件中卻是香餑餑,我們消息中間件 RocketMQ 為例。

88b1137a-82d4-11ee-939d-92fbcf53809c.jpg

上圖是 RocketMQ 的集群模式 ,Broker 分為 Master 與 Slave,一個 Master 可以對應(yīng)多個 Slave,但是一個 Slave 只能對應(yīng)一個 Master。

每個 Broker 與 Name Server 集群中的所有節(jié)點建立長連接,定時每隔 30 秒注冊 主題的路由信息到所有 Name Server。

消息發(fā)送者、消息消費者,在同一時間只會連接 Name Server 集群中的一臺服務(wù)器,并且會每隔 30s 會定時更新 Topic 的路由信息。

我們可以理解 Name Server 集群的作用就是注冊中心,注冊中心會保存路由信息(主題的讀寫隊列數(shù)、操作權(quán)限等),路由信息就是保存在 HashMap 中 。

88c56532-82d4-11ee-939d-92fbcf53809c.jpg

路由信息通過幾個 HashMap 來保存,當(dāng) Broker 向 Nameserver 發(fā)送心跳包(路由信息),Nameserver 需要對 HashMap 進(jìn)行數(shù)據(jù)更新,但我們都知道 HashMap 并不是線程安全的,高并發(fā)場景下,容易出現(xiàn) CPU 100% 問題,所以更新 HashMap 時需要加鎖,RocketMQ 使用了 JDK 的讀寫鎖 ReentrantReadWriteLock 。

下面我們看下路由信息如何更新和讀?。?/p>

1、寫操作:更新路由信息,操作寫鎖

88d51266-82d4-11ee-939d-92fbcf53809c.jpg

2、讀操作:查詢主題信息,操作讀鎖

88e026a6-82d4-11ee-939d-92fbcf53809c.jpg

同時,我們需要注意 Name Server 維護(hù)路由信息還需要定時任務(wù)的支撐。

每個 Broker 定時每隔 30 秒注冊 主題的路由信息到所有 Name Server

Name Server 定時任務(wù)每隔10 秒清除已宕機(jī)的 Broker

我們做一個小小的總結(jié),Name Server 維護(hù)路由的模式是:HashMap + 讀寫鎖 + 定時任務(wù)更新。

HashMap 作為存儲容器

讀寫鎖控制鎖的顆粒度

定時任務(wù)定時更新緩存

寫到這里,我們不禁想到 ConcurrentHashMap。

ConcurrentHashMap 可以保證線程安全,JDK1.7 之前使用分段鎖機(jī)制實現(xiàn),JDK1.8 則使用數(shù)組+鏈表+紅黑樹數(shù)據(jù)結(jié)構(gòu)和CAS原子操作實現(xiàn)。

Broker 使用不同的 ConcurrentHashMap 分別用來存儲消費組、消費進(jìn)度、消息過濾信息等。

那么名字服務(wù)為什么不使用 ConcurrentHashMap 作為存儲容器呢 ?

最核心的原因在于:路由信息由多個 HashMap 組成,通過每次寫操作可能要操作多個對象 ,為了保證其一致性,所以才需要加讀寫鎖。

基于 Spring Boot + MyBatis Plus + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

項目地址:https://github.com/YunaiV/ruoyi-vue-pro

視頻教程:https://doc.iocoder.cn/video/

2 LinkedHashMap 最近最少使用緩存

LinkedHashMap 是 HashMap 的子類,但是內(nèi)部還有一個雙向鏈表維護(hù)鍵值對的順序,每個鍵值對既位于哈希表中,也位于雙向鏈表中。

LinkedHashMap 支持兩種順序插入順序 、 訪問順序。

插入順序:先添加的在前面,后添加的在后面,修改操作并不影響順序

訪問順序:問指的是 get/put 操作,對一個鍵執(zhí)行 get/put 操作后,其對應(yīng)的鍵值對會移動到鏈表末尾,所以最末尾的是最近訪問的,最開始的是最久沒有被訪問的,這就是訪問順序。

LinkedHashMap 經(jīng)典的用法是作為 LruCache (最近最少使用緩存) ,而 MyBatis 的二級緩存的淘汰機(jī)制就是使用的 LinkedHashMap 。

MyBatis 的二級緩存是使用責(zé)任鏈+ 裝飾器的設(shè)計模式實現(xiàn)的。

88e74e0e-82d4-11ee-939d-92fbcf53809c.jpg

上圖中,裝飾器包目錄下 Cache 接口有不同的實現(xiàn)類,比如過期淘汰、日志記錄等。

88ef3088-82d4-11ee-939d-92fbcf53809c.jpg

LruCache 使用了裝飾器模式 ,使用 LinkedHashMap 默認(rèn)保存 1024 個緩存 key ,當(dāng) key 最久未被訪問,并且 keyMap 的大小超過 1024 時 ,記錄最老的 key ,當(dāng)下次添加緩存對象時,刪除最老的 key。

使用 LinkedHashMap 重點需要做到使用訪問順序模式和重寫 removeEldestEntry 方法。因為 LinkedHashMap 并不是線程安全的,Mybatis 二級緩存責(zé)任鏈中 SynchronizedCache 對象可以實現(xiàn)線程安全的對緩存讀寫。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

項目地址:https://github.com/YunaiV/yudao-cloud

視頻教程:https://doc.iocoder.cn/video/

3 TreeMap 排序?qū)ο缶彺?/p>

TreeMap 是一種基于紅黑樹的有序 Map,它可以按照鍵的順序進(jìn)行遍歷。

TreeMap 有兩種應(yīng)用場景讓筆者印象極為深刻 ,他們分別是一致性哈希算法和 RocketMQ 消費快照 。

下面重點介紹 TreeMap 在一致性哈希算法中的應(yīng)用。

一致性哈希(Consistent Hashing)算法被廣泛應(yīng)用于緩存系統(tǒng)、分布式數(shù)據(jù)庫、負(fù)載均衡器等分布式系統(tǒng)中,以實現(xiàn)高性能和高可用性。它解決了傳統(tǒng)哈希算法在動態(tài)環(huán)境下擴(kuò)展性和負(fù)載均衡性能的問題。

一致性哈希的主要優(yōu)點是在節(jié)點增減時,只有少量的數(shù)據(jù)需要重新映射,因為只有那些直接或間接與新增或刪除節(jié)點相鄰的數(shù)據(jù)項需要遷移。這大大減少了系統(tǒng)的遷移開銷和影響,使得系統(tǒng)更具擴(kuò)展性和可伸縮性。

TreeMap 在一致性哈希中可以用作節(jié)點/虛擬節(jié)點的存儲結(jié)構(gòu),用來維護(hù)節(jié)點在哈希環(huán)上的位置和鍵的有序性。

1、我們定義一個 TreeMap 存儲節(jié)點/虛擬節(jié)點 。

890959fe-82d4-11ee-939d-92fbcf53809c.png

2、初始化節(jié)點

構(gòu)造函數(shù)包含三個部分:物理節(jié)點集合、每個物理節(jié)點對應(yīng)的虛擬節(jié)點個數(shù)、哈希函數(shù) 。

89146614-82d4-11ee-939d-92fbcf53809c.png

我們重點看下添加節(jié)點邏輯:

891dd2e4-82d4-11ee-939d-92fbcf53809c.png

3、按照 key 查詢節(jié)點

添加完節(jié)點之后,節(jié)點分布類似下圖:

8935c548-82d4-11ee-939d-92fbcf53809c.jpg

893fe244-82d4-11ee-939d-92fbcf53809c.png

當(dāng)需要定位某個 key 屬于哪個節(jié)點時,先通過哈希函數(shù)計算 key 的哈希值,并在環(huán)上順時針方向找到第一個大于等于該哈希值的節(jié)點位置。該節(jié)點即為數(shù)據(jù)的歸屬節(jié)點 。

我們添加一個新的節(jié)點 node5 , 從下圖中,我們可以看到,影響的范圍(深黃色)并不大 ,這也就是一致性哈希算法的優(yōu)勢。

8956c536-82d4-11ee-939d-92fbcf53809c.jpg

4 ByteBuffer 網(wǎng)絡(luò)編程緩沖池

ByteBuffer 是字節(jié)緩沖區(qū),主要用于用戶讀取和緩存字節(jié)數(shù)據(jù),多用于網(wǎng)絡(luò)編程、文件 IO 處理等。

筆者第一次接觸 ByteBuffer 是在分庫分表中間件 Cobar 中 。在網(wǎng)絡(luò)編程里,經(jīng)常需要分配內(nèi)存,在高并發(fā)場景下,性能壓力比較大。

Cobar 抽象了一個 NIOProcessor 類用來處理網(wǎng)絡(luò)請求,每個處理器初始化的時候都會創(chuàng)建一個緩沖池 BufferPool 。BufferPool 用于池化 ByteBuffer ,這和我們平常使用的數(shù)據(jù)庫連接池的思路是一致的。

8964ec9c-82d4-11ee-939d-92fbcf53809c.png

下圖展示了緩沖池 BufferPool 的源碼:

896fb83e-82d4-11ee-939d-92fbcf53809c.png

緩沖池 BufferPool 的核心功能是分配緩存和回收緩存 ,通過將緩存池化,可以大大提升系統(tǒng)的性能。

如今 ,Netty 內(nèi)置了更為強(qiáng)大的內(nèi)存池化工具 ByteBuf ,我們會在后面的文章里詳聊。

5 寫到最后

這篇文章,筆者總結(jié)了四種強(qiáng)大且低調(diào)的緩存。

1、HashMap/ConcurrentHashMap 經(jīng)常用于配置緩存,對于 HashMap 來講,HashMap + 讀寫鎖 + 定時任務(wù)更新是常用的模式。而 ConcurrentHashMap 廣泛存在于各種中間件,線程安全且靈活易用。

2、LinkedHashMap 經(jīng)常被用于創(chuàng)建最近最少使用緩存 LruCache 。推薦學(xué)習(xí) Mybatis 二級緩存的設(shè)計,它使用責(zé)任鏈+ 裝飾器的設(shè)計模式,內(nèi)置 LruCache 的實現(xiàn)就是使用 LinkedHashMap 。

3、TreeMap 是一種基于紅黑樹的有序 Map 。TreeMap 在一致性哈希中可以用作節(jié)點/虛擬節(jié)點的存儲結(jié)構(gòu),用來維護(hù)節(jié)點在哈希環(huán)上的位置和鍵的有序性。

4、ByteBuffer 是字節(jié)緩沖區(qū),主要用于用戶讀取和緩存字節(jié)數(shù)據(jù),多用于網(wǎng)絡(luò)編程、文件 IO 處理等。分庫分表中間件 Cobar 在網(wǎng)絡(luò)請求處理中,創(chuàng)建了緩沖池 BufferPool 用于池化 ByteBuffer ,從而大大提升系統(tǒng)的性能。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • JAVA
    +關(guān)注

    關(guān)注

    20

    文章

    2989

    瀏覽量

    109924
  • 緩存
    +關(guān)注

    關(guān)注

    1

    文章

    246

    瀏覽量

    27200
  • 程序員
    +關(guān)注

    關(guān)注

    4

    文章

    954

    瀏覽量

    30424

原文標(biāo)題:盤點那些強(qiáng)大又低調(diào)的 Java 緩存

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    Nginx緩存配置詳解

    Nginx 是一個功能強(qiáng)大的 Web 服務(wù)器和反向代理服務(wù)器,它可以用于實現(xiàn)靜態(tài)內(nèi)容的緩存,緩存可以分為客戶端緩存和服務(wù)端緩存。
    的頭像 發(fā)表于 05-07 14:03 ?600次閱讀
    Nginx<b class='flag-5'>緩存</b>配置詳解

    如何選擇合適的本地緩存?

    的 Guava 緩存、在 Guava 上進(jìn)一步傳承的 Caffine 以及自稱在 Java 中使用最廣泛的 EhCache,那么我們該怎么選擇適合自己應(yīng)用的緩存呢,小編下面會簡單介紹,并將以上
    的頭像 發(fā)表于 01-18 11:19 ?1143次閱讀
    如何選擇合適的本地<b class='flag-5'>緩存</b>?

    基于Java的分布式緩存優(yōu)化在網(wǎng)絡(luò)管理系統(tǒng)中的應(yīng)用

    基于Java的分布式緩存優(yōu)化在網(wǎng)絡(luò)管理系統(tǒng)中的應(yīng)用討論建立在JMX管理框架上的網(wǎng)絡(luò)性能管理系統(tǒng)的優(yōu)化方案,利用JMX體系結(jié)構(gòu)的可擴(kuò)展特性,在系統(tǒng)的服務(wù)器端嵌入了分布式緩存系統(tǒng)對服務(wù)器端的緩存
    發(fā)表于 09-19 09:20

    ASP緩存技術(shù)

    緩存中時,再次查詢時耗費的時間主要是在顯示數(shù)據(jù)的時間上了。也就是說,我們不應(yīng)該把經(jīng)常需要改變的數(shù)據(jù)放到服務(wù)端的緩存中,我們應(yīng)該把改變少,但是需要經(jīng)常訪問的數(shù)據(jù)放到緩存中?,F(xiàn)在我們先
    發(fā)表于 11-21 10:53

    Java中的輸入輸出流盤點

    Java中的流分為兩種,一種是字節(jié)流,另一種是字符流,分別由四個抽象類來表示(每種流包括輸入和輸出兩種所以一共四個):InputStream,OutputStream,Reader,Writer。Java中其他多種多樣變化的流均是由它們派生出來的。
    發(fā)表于 07-11 07:56

    Java程序員筆記之mybatis結(jié)合redis實戰(zhàn)二級緩存

    Java程序員筆記——mybatis結(jié)合redis實戰(zhàn)二級緩存
    發(fā)表于 06-10 09:15

    Java 使用Redis緩存工具的詳細(xì)解說

    本文是關(guān)于Java 使用Redis緩存工具的詳細(xì)解說。詳細(xì)步驟請看下文
    的頭像 發(fā)表于 02-09 14:10 ?8055次閱讀
    <b class='flag-5'>Java</b> 使用Redis<b class='flag-5'>緩存</b>工具的詳細(xì)解說

    TicWatchPro體驗 獨立強(qiáng)大的智能手表

    智能可穿戴設(shè)備最早只存在于科幻電影中,無論是項鏈還是手表,功能強(qiáng)大百變的“特工用具”讓我們興奮不已。都說科幻電影在一定程度上反映、引領(lǐng)了未來科技的發(fā)展,我們也不停的在問,那些電影中炫酷的黑科技何時才能真正“飛入尋常百姓家”呢?
    的頭像 發(fā)表于 01-21 10:34 ?3362次閱讀

    盤點嵌入式的那些常見GUI:emWin、TouchGFX、MiniGUI、Qt等

    盤點嵌入式那些常見的GUI:emWin、TouchGFX、MiniGUI、Qt等
    的頭像 發(fā)表于 02-05 12:38 ?1w次閱讀

    盤點CES2020上的那些機(jī)器人

    美國消費電子展CES 2020接近尾聲,這次展會上機(jī)器人依舊是一個吸引大眾目光的領(lǐng)域。技術(shù)的不斷革新,讓機(jī)器人或者機(jī)械骨骼們開始應(yīng)用到各種領(lǐng)域之中。下面,就讓我們來為盤點一下本屆CES上那些閃耀全場的機(jī)器人吧。
    的頭像 發(fā)表于 01-10 17:54 ?3519次閱讀

    Redis集群緩存方案,緩存常見問題盤點

    如今,緩存系統(tǒng)的應(yīng)用非常廣泛,能夠用來提高并發(fā)數(shù)、數(shù)據(jù)吞吐量,提高快速響應(yīng)能力。那么當(dāng)數(shù)據(jù)量達(dá)到一定程度,單機(jī)環(huán)境可能就顯得有些力不從心了,就需要一個分布式緩存系統(tǒng)。
    發(fā)表于 12-16 10:48 ?2370次閱讀
    Redis集群<b class='flag-5'>緩存</b>方案,<b class='flag-5'>緩存</b>常見問題<b class='flag-5'>盤點</b>

    關(guān)于內(nèi)存緩存那些

    而包含和不包含的區(qū)別在這里就會有所體現(xiàn)。如果是包含策略,那么新數(shù)據(jù)直接覆蓋舊數(shù)據(jù)即可,舊數(shù)據(jù)等于直接作廢,除非這個數(shù)據(jù)最近在CPU中被改寫過,需要返回到內(nèi)存中進(jìn)行保存,那么才需要將該緩存行刷回內(nèi)存(那么如何確定該緩存行是否被改寫過呢?可以用一個名為dirty的標(biāo)志位注明)
    的頭像 發(fā)表于 08-03 16:59 ?3367次閱讀
    關(guān)于內(nèi)存<b class='flag-5'>緩存</b>的<b class='flag-5'>那些</b>事

    Ehcache!這才是Java本地緩存之王!

    Java而言,其常用的緩存解決方案有很多,例如數(shù)據(jù)庫緩存框架EhCache,分布式緩存Memcached等,這些緩存方案實際上都是為了提升
    的頭像 發(fā)表于 07-29 11:21 ?2377次閱讀
    Ehcache!這才是<b class='flag-5'>Java</b>本地<b class='flag-5'>緩存</b>之王!

    基于java開發(fā)的緩存框架jetcache簡介

    在實際應(yīng)用中,并不是單一的使用本地緩存或者redis,更多是組合使用來滿足不同的業(yè)務(wù)場景,于是如何優(yōu)雅的組合本地緩存和遠(yuǎn)程緩存就成了我們要研究的問題,而這一點,阿里開源的jetcache組件幫我們實現(xiàn)了
    的頭像 發(fā)表于 09-07 10:36 ?2296次閱讀
    基于<b class='flag-5'>java</b>開發(fā)的<b class='flag-5'>緩存</b>框架jetcache簡介

    CPU緩存那些事兒

    CPU Cache 在讀取內(nèi)存數(shù)據(jù)時,每次不會只讀一個字或一個字節(jié),而是一塊塊地讀取,這每一小塊數(shù)據(jù)也叫CPU 緩存行(CPU Cache Line)。這也是對局部性原理的運用,當(dāng)一個指令或數(shù)據(jù)被
    的頭像 發(fā)表于 09-10 10:57 ?959次閱讀
    CPU<b class='flag-5'>緩存</b><b class='flag-5'>那些</b>事兒