本文探討了各種Java緩存技術(shù)的提供,這些技術(shù)在改善應(yīng)用程序性能方面發(fā)揮著至關(guān)重要的作用,并涵蓋了各種場景。
幾十年來,信息技術(shù)一直在極大地改善業(yè)務(wù)流程,并成為全球企業(yè)的戰(zhàn)略解決方案。曾經(jīng)被視為“可有可無”的東西現(xiàn)在已經(jīng)成為必備之物。應(yīng)用程序是任何業(yè)務(wù)的核心,在近年來,它們的使用量大幅增加。因此,響應(yīng)時間變得更加重要。數(shù)據(jù)檢索時間在用戶體驗中起著關(guān)鍵作用,并且在幾乎所有商業(yè)應(yīng)用程序中都是一個關(guān)鍵要求。如今有許多影響響應(yīng)時間的因素,包括網(wǎng)絡(luò)管道、協(xié)議、硬件、軟件和互聯(lián)網(wǎng)速度。龐大的IT基礎(chǔ)設(shè)施和對系統(tǒng)性能的不斷追求嚴(yán)重破壞了任何組織的戰(zhàn)略目標(biāo)。
本文旨在介紹一種Java緩存機制,以改善應(yīng)用程序的性能。
緩存概念
緩存是用于臨時存儲頻繁訪問的數(shù)據(jù)的內(nèi)存緩沖區(qū)。它通過避免從原始來源再次檢索數(shù)據(jù)來提高性能。實際上,緩存是計算機/網(wǎng)絡(luò)行業(yè)的一個已經(jīng)應(yīng)用了相當(dāng)長時間的概念,因此根據(jù)使用情況有不同的緩存實現(xiàn)方式。事實上,路由器、交換機和個人電腦等設(shè)備都使用緩存來加速內(nèi)存訪問。另一個非常常見的緩存是在幾乎所有個人電腦上使用的Web瀏覽器緩存,用于存儲請求的對象,以避免多次檢索相同的數(shù)據(jù)。在分布式JEE應(yīng)用程序中,客戶端/服務(wù)器端緩存在改善應(yīng)用程序性能方面起著重要作用??蛻舳司彺嬗糜谂R時存儲通過網(wǎng)絡(luò)從服務(wù)器傳輸?shù)撵o態(tài)數(shù)據(jù),以避免不必要地向服務(wù)器發(fā)出調(diào)用。另一方面,服務(wù)器端緩存用于存儲從其他資源獲取的數(shù)據(jù)。
緩存可以設(shè)計為單個/多個JVM或集群環(huán)境。以下是可使用緩存滿足非功能性要求的不同可擴展性場景。
縱向擴展
可以通過升級單臺機器的資源(CPU、RAM、HDD和SSD)并實施緩存來實現(xiàn)。但是,在將緩存升級到一定限制上存在一些局限性。在下面的用例中,可以通過增加內(nèi)存并在應(yīng)用程序級別實施緩存來提高應(yīng)用程序的性能。
橫向擴展
可以通過添加更多的機器并在每臺機器上實施應(yīng)用程序級別的緩存來實現(xiàn)。但是,在與下游應(yīng)用程序通信方面仍然存在一些限制,無法添加額外的服務(wù)器。在下面的用例中,可以通過為每個應(yīng)用程序添加一個服務(wù)器/緩存來提高整體應(yīng)用程序的性能。數(shù)據(jù)庫在滿足此要求方面存在一些限制,但可以通過將靜態(tài)/主數(shù)據(jù)存儲在緩存中來減輕這種限制。
進(jìn)程內(nèi)緩存
進(jìn)程內(nèi)緩存使對象能夠存儲在與應(yīng)用程序相同的實例中,即緩存在本地對應(yīng)用程序可用,并共享相同的內(nèi)存空間。
以下是考慮進(jìn)程內(nèi)緩存時的一些重要事項:
如果應(yīng)用程序僅部署在一個節(jié)點上,即只有一個實例,則進(jìn)程內(nèi)緩存是正確的選擇,可以存儲頻繁訪問的數(shù)據(jù)并實現(xiàn)快速數(shù)據(jù)訪問。
如果進(jìn)程內(nèi)緩存將在應(yīng)用程序的多個實例中部署,則在所有實例之間保持?jǐn)?shù)據(jù)同步可能是一個挑戰(zhàn),并可能導(dǎo)致數(shù)據(jù)不一致。
如果服務(wù)器配置有限,則這種類型的緩存可能會降低任何應(yīng)用程序的性能,因為它共享相同的內(nèi)存和CPU。垃圾收集器經(jīng)常被調(diào)用來清理可能導(dǎo)致性能開銷的對象。如果數(shù)據(jù)驅(qū)逐沒有有效管理,可能會發(fā)生內(nèi)存溢出錯誤。
內(nèi)存分布式緩存
分布式緩存(鍵/值對象)可以在應(yīng)用程序外部構(gòu)建,支持對數(shù)據(jù)存儲庫的讀寫操作,在RAM中保存頻繁訪問的數(shù)據(jù),并避免不斷從數(shù)據(jù)源獲取數(shù)據(jù)。這樣的緩存可以部署在由多個節(jié)點組成的集群上,形成一個單一的邏輯視圖。緩存客戶端使用哈希算法來確定集群節(jié)點中對象的位置。
以下是考慮分布式緩存時的一些重要事項:
對于在關(guān)鍵性能環(huán)境下具有多個實例的集群中的中大型應(yīng)用程序,內(nèi)存分布式緩存是最佳選擇。數(shù)據(jù)不一致性和共享內(nèi)存不再是問題,因為分布式緩存以單一邏輯狀態(tài)的形式部署在集群中。
由于需要通過網(wǎng)絡(luò)訪問緩存,跨進(jìn)程的開銷包括延遲、故障以及對象序列化等,可能會降低性能。
與進(jìn)程內(nèi)緩存相比,其實現(xiàn)更加困難。
內(nèi)存數(shù)據(jù)庫
這種類型的數(shù)據(jù)庫也被稱為主存數(shù)據(jù)庫。它將數(shù)據(jù)存儲在RAM中,而不是硬盤上,以實現(xiàn)更快的響應(yīng)。數(shù)據(jù)以壓縮格式存儲,并具有良好的SQL支持??梢允褂孟嚓P(guān)的數(shù)據(jù)庫驅(qū)動程序來替代現(xiàn)有的關(guān)系數(shù)據(jù)庫管理系統(tǒng)(RDBMS)。
通過用內(nèi)存數(shù)據(jù)庫替換RDBMS,可以提高應(yīng)用程序的性能,而無需更改應(yīng)用程序?qū)?。只能進(jìn)行縱向擴展以擴大內(nèi)存數(shù)據(jù)庫的規(guī)模。
內(nèi)存數(shù)據(jù)網(wǎng)格
這種分布式緩存解決方案可以快速訪問頻繁使用的數(shù)據(jù)。數(shù)據(jù)可以在多個節(jié)點上進(jìn)行緩存、復(fù)制和分區(qū)。
實施內(nèi)存數(shù)據(jù)網(wǎng)格將提高應(yīng)用程序的性能并擴展其規(guī)模,而無需更改關(guān)系數(shù)據(jù)庫管理系統(tǒng)(RDBMS)。
關(guān)鍵特點包括:
在內(nèi)存中對數(shù)據(jù)進(jìn)行并行計算
在內(nèi)存中進(jìn)行搜索、聚合和排序
在內(nèi)存中進(jìn)行事務(wù)管理
事件處理
緩存的使用場景
有一些使用場景可以通過各種商業(yè)/開源緩存框架來提高應(yīng)用程序性能,并且可以在任何企業(yè)應(yīng)用程序中進(jìn)行配置。以下是常見的緩存使用場景。
應(yīng)用程序緩存
應(yīng)用程序緩存是應(yīng)用程序使用的本地緩存,用于將頻繁訪問的數(shù)據(jù)保留在內(nèi)存中。應(yīng)用程序緩存會自動驅(qū)逐條目以維護(hù)其內(nèi)存占用。
Level 1 (L1) Cache
這是每個會話的默認(rèn)事務(wù)性緩存。它可以由任何Java持久化框架(JPA)或?qū)ο箨P(guān)系映射(ORM)工具進(jìn)行管理。
L1緩存存儲屬于特定會話的實體對象,并在會話關(guān)閉后被清除。如果在一個會話中有多個事務(wù),所有實體將來自這些事務(wù)。
Level 2 (L2) Cache
L2緩存可以配置為提供自定義緩存,用于保存所有需要緩存的實體數(shù)據(jù),包括屬性、關(guān)聯(lián)和集合。它在會話工廠級別進(jìn)行配置,并在會話工廠可用時存在。
L2緩存可以配置為在以下范圍內(nèi)使用:
應(yīng)用程序中的會話。
具有相同數(shù)據(jù)庫的相同服務(wù)器上的應(yīng)用程序。
同一數(shù)據(jù)庫上不同服務(wù)器上的不同應(yīng)用程序的集群。
如果配置了L2緩存,則可以使用L1/L2緩存的方式:
標(biāo)準(zhǔn)的ORM框架首先在L1緩存中查找實體,然后再在L2緩存中查找。L1緩存是查找實體的初始搜索空間。如果找到實體的緩存副本,則返回該實體。
如果在L1緩存中找不到緩存的實體,則會在L2緩存中進(jìn)行查找。
如果在L2緩存中找到緩存的實體,則將其存儲在L1緩存中,然后返回。
如果實體既不在L1緩存中也不在L2緩存中,則從數(shù)據(jù)庫中獲取該實體,并在返回給調(diào)用方之前將其存儲在兩個緩存中。
當(dāng)任何會話對實體進(jìn)行修改時,L2緩存會進(jìn)行驗證/刷新。
如果數(shù)據(jù)庫被外部進(jìn)程修改,即沒有應(yīng)用程序會話參與,那么除非通過框架API或自定義API實現(xiàn)某種緩存刷新策略,否則無法隱式刷新L2緩存。
以下通信圖說明了使用L1/L2緩存的情況:
混合緩存
混合緩存是標(biāo)準(zhǔn)ORM框架提供的緩存與開源/自定義/JDBC API實現(xiàn)的緩存的結(jié)合。應(yīng)用程序可以使用混合緩存來利用僅限于標(biāo)準(zhǔn)ORM框架的緩存功能。這種類型的緩存通常在響應(yīng)時間至關(guān)重要的關(guān)鍵任務(wù)應(yīng)用程序中使用。
緩存設(shè)計考慮因素
緩存設(shè)計時需要考慮數(shù)據(jù)加載/更新、性能/內(nèi)存大小、逐出策略、并發(fā)性和緩存統(tǒng)計等因素。
數(shù)據(jù)加載/更新
將數(shù)據(jù)加載到緩存中是一個重要的設(shè)計決策,以保持所有緩存內(nèi)容的一致性??梢钥紤]以下方法來加載數(shù)據(jù):
使用標(biāo)準(zhǔn)ORM框架(如Hibernate或OpenJPA)提供的默認(rèn)函數(shù)/配置。
使用開源緩存API(如Google Guava)或COTS產(chǎn)品(如Coherence、Ehcache或Hazelcast)實現(xiàn)鍵值映射。
通過自動或顯式插入編程方式加載實體。
通過同步或異步通信進(jìn)行外部應(yīng)用程序加載。
性能/內(nèi)存大小 32/64位
可用內(nèi)存是實現(xiàn)性能SLA的重要因素,它取決于32/64位JRE,而后者又依賴于32/64位CPU架構(gòu)的機器。在32位系統(tǒng)/JRE中,約有1.5 GB的堆留給應(yīng)用程序使用,而在64位系統(tǒng)/JRE中,堆大小取決于RAM大小。
內(nèi)存的高可用性會增加運行時的成本,并可能產(chǎn)生負(fù)面影響。
與32位相比,64位需要30-50%更多的堆空間,因為內(nèi)存布局不同。
維護(hù)更大的堆空間需要更多的GC工作來清理未使用的對象,可能會降低性能??梢酝ㄟ^調(diào)整GC進(jìn)行微調(diào)以限制GC暫停時間。
逐出策略
逐出策略使緩存能夠確保緩存的大小不超過最大限制。根據(jù)逐出策略,會從緩存中刪除現(xiàn)有元素,但可以根據(jù)應(yīng)用程序要求進(jìn)行定制。常用的緩存逐出算法有:
最近最少使用(LRU)
最不經(jīng)常使用(LFU)
先進(jìn)先出(FIFO)
并發(fā)性
并發(fā)性是企業(yè)應(yīng)用程序中常見的問題。它會導(dǎo)致沖突并使系統(tǒng)處于不一致狀態(tài)。當(dāng)多個客戶端在緩存刷新期間同時嘗試更新相同的數(shù)據(jù)對象時,就會發(fā)生并發(fā)性問題。常見的解決方案是使用鎖定機制,但這可能會影響性能。因此,應(yīng)考慮優(yōu)化技術(shù)。
緩存統(tǒng)計
緩存統(tǒng)計信息有助于了解緩存的健康狀況,并提供有關(guān)緩存行為和性能的信息。通常,可以使用以下屬性來進(jìn)行緩存統(tǒng)計:
命中計數(shù):找到對象時遇到的查找次數(shù)
未命中計數(shù):未找到對象時遇到的查找次數(shù)
成功加載計數(shù):成功加載條目的數(shù)量
總加載時間:加載元素所用的總時間
加載異常計數(shù):加載條目時拋出的異常數(shù)量
逐出計數(shù):從緩存中逐出的條目數(shù)
概述:各種緩存解決方案
Java有多種可用的緩存解決方案 - 找到適合您的用例的正確選擇取決于您的需求。以下是一些問題和比較,可幫助確定最具成本效益且可行的緩存解決方案:
您需要一個輕量級還是完整的緩存解決方案?
您需要一個開源、商業(yè)還是框架提供的緩存解決方案?
您需要進(jìn)程內(nèi)還是分布式緩存?
一致性和延遲需求之間的權(quán)衡如何?
您是否需要維護(hù)事務(wù)性/主數(shù)據(jù)的緩存?
您是否需要復(fù)制緩存?
關(guān)于性能、可靠性、可擴展性和可用性方面有什么要考慮的?
根據(jù)這些問題和比較,您可以確定最適合您需求的成本效益和可行性的緩存解決方案。
緩存解決方案 | 緩存類型 | 開源 | 復(fù)制 | (JSR-107)兼容 | 配置復(fù)雜性 | 逐出算法 | 集群支持 |
---|---|---|---|---|---|---|---|
Ehcache | Level 2級別 | 是 | 是 | 是 | 簡單 | LRU, LFU | 是 |
Hazelcast | Level 2級別 | 是 | 是 | 是 | 簡單 | LRU, LFU | 是 |
Redis/Memcached | 分布式 | 是 | 是 | 是 | 中等 | LRU | 是 |
Google Guava | 進(jìn)程內(nèi) | 是 | 否 | - | 簡單 | LRU | 否 |
Coherence | 分布式 | 否 | 是 | 是 | 復(fù)雜 | LRU, LFU, 混合, 自定義 | 是 |
請注意,復(fù)制緩存意味著緩存可以在集群中多個節(jié)點之間維護(hù)相同的數(shù)據(jù)副本。這有助于實現(xiàn)高可用性和容錯性。
(JSR-107)兼容表示符合Java Caching API標(biāo)準(zhǔn),該標(biāo)準(zhǔn)提供了一組用于在Java中進(jìn)行緩存的公共接口和功能。
配置復(fù)雜性指的是配置和設(shè)置緩存解決方案的難易程度。
逐出算法確定在緩存達(dá)到最大大小時從中刪除哪些元素。LRU表示最近最少使用,F(xiàn)LU表示最不經(jīng)常使用,LFU表示最頻繁使用率最低。
集群支持表示緩存解決方案是否支持集群,并能夠?qū)?shù)據(jù)分布在集群中的多個節(jié)點之間。
根據(jù)這些因素,您可以選擇最適合您特定需求的緩存解決方案。文章來源:http://www.zghlxwxcb.cn/article/636.html
關(guān)鍵詞:Java緩存技術(shù),改善應(yīng)用程序性能,性能優(yōu)化,內(nèi)存緩存文章來源地址http://www.zghlxwxcb.cn/article/636.html
到此這篇關(guān)于如何優(yōu)化應(yīng)用程序性能的內(nèi)存緩存解決方案-Java緩存技術(shù)的文章就介紹到這了,更多相關(guān)內(nèi)容可以在右上角搜索或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!