微服務08-多級緩存

1.什么是多級緩存

傳統的緩存策略一般是請求到達Tomcat后,先查詢Redis,如果未命中則查詢數據庫,如圖:
在這里插入圖片描述

存在下面的問題:

?請求要經過Tomcat處理,Tomcat的性能成為整個系統的瓶頸

?Redis緩存失效時,會對數據庫產生沖擊

多級緩存就是充分利用請求處理的每個環節,分別添加緩存,減輕Tomcat壓力,提升服務性能:

  • 瀏覽器訪問靜態資源時,優先讀取瀏覽器本地緩存
  • 訪問非靜態資源(ajax查詢數據)時,訪問服務端
  • 請求到達Nginx后,優先讀取Nginx本地緩存
  • 如果Nginx本地緩存未命中,則去直接查詢Redis(不經過Tomcat)
  • 如果Redis查詢未命中,則查詢Tomcat
  • 請求進入Tomcat后,優先查詢JVM進程緩存
  • 如果JVM進程緩存未命中,則查詢數據庫
    在這里插入圖片描述

在多級緩存架構中,Nginx內部需要編寫本地緩存查詢、Redis查詢、Tomcat查詢的業務邏輯,因此這樣的nginx服務不再是一個反向代理服務器,而是一個編寫業務的Web服務器了

因此這樣的業務Nginx服務也需要搭建集群來提高并發,再有專門的nginx服務來做反向代理,如圖:
在這里插入圖片描述

另外,我們的Tomcat服務將來也會部署為集群模式:
在這里插入圖片描述

可見,多級緩存的關鍵有兩個:

  • 一個是在nginx中編寫業務,實現nginx本地緩存、Redis、Tomcat的查詢

  • 另一個就是在Tomcat中實現JVM進程緩存

其中Nginx編程則會用到OpenResty框架結合Lua這樣的語言。

2.JVM進程緩存

2.2.初識Caffeine

緩存在日常開發中啟動至關重要的作用,由于是存儲在內存中,數據的讀取速度是非常快的,能大量減少對數據庫的訪問,減少數據庫的壓力。我們把緩存分為兩類:

  • 分布式緩存,例如Redis:
    • 優點:存儲容量更大、可靠性更好、可以在集群間共享
    • 缺點:訪問緩存有網絡開銷
    • 場景:緩存數據量較大、可靠性要求較高、需要在集群間共享
  • 進程本地緩存,例如HashMap、GuavaCache:
    • 優點:讀取本地內存,沒有網絡開銷,速度更快
    • 缺點:存儲容量有限、可靠性較低、無法共享
    • 場景:性能要求較高,緩存數據量較小

利用Caffeine框架來實現JVM進程緩存。

Caffeine是一個基于Java8開發的,提供了近乎最佳命中率的高性能的本地緩存庫。目前Spring內部的緩存使用的就是Caffeine。GitHub地址:https://github.com/ben-manes/caffeine

緩存使用的基本API:

@Test
void testBasicOps() {// 構建cache對象Cache<String, String> cache = Caffeine.newBuilder().build();// 存數據cache.put("gf", "迪麗熱巴");// 取數據String gf = cache.getIfPresent("gf");System.out.println("gf = " + gf);// 取數據,包含兩個參數:// 參數一:緩存的key// 參數二:Lambda表達式,表達式參數就是緩存的key,方法體是查詢數據庫的邏輯// 優先根據key查詢JVM緩存,如果未命中,則執行參數二的Lambda表達式String defaultGF = cache.get("defaultGF", key -> {// 根據key去數據庫查詢數據return "柳巖";});System.out.println("defaultGF = " + defaultGF);
}

Caffeine既然是緩存的一種,肯定需要有緩存的清除策略,不然的話內存總會有耗盡的時候。

Caffeine提供了三種緩存驅逐策略:

  • 基于容量:設置緩存的數量上限

    // 創建緩存對象
    Cache<String, String> cache = Caffeine.newBuilder().maximumSize(1) // 設置緩存大小上限為 1.build();
    
  • 基于時間:設置緩存的有效時間

    // 創建緩存對象
    Cache<String, String> cache = Caffeine.newBuilder()// 設置緩存有效期為 10 秒,從最后一次寫入開始計時 .expireAfterWrite(Duration.ofSeconds(10)) .build();
  • 基于引用:設置緩存為軟引用或弱引用,利用GC來回收緩存數據。性能較差,不建議使用。

注意:在默認情況下,當一個緩存元素過期的時候,Caffeine不會自動立即將其清理和驅逐。而是在一次讀或寫操作后,或者在空閑時間完成對失效數據的驅逐。

2.3.實現JVM進程緩存

2.3.1.需求

利用Caffeine實現下列需求:

  • 給根據id查詢商品的業務添加緩存,緩存未命中時查詢數據庫
  • 給根據id查詢商品庫存的業務添加緩存,緩存未命中時查詢數據庫
  • 緩存初始大小為100
  • 緩存上限為10000

2.3.2.實現

首先,我們需要定義兩個Caffeine的緩存對象,分別保存商品、庫存的緩存數據。

在item-service的com.heima.item.config包下定義CaffeineConfig類:

package com.heima.item.config;import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.heima.item.pojo.Item;
import com.heima.item.pojo.ItemStock;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class CaffeineConfig {@Beanpublic Cache<Long, Item> itemCache(){return Caffeine.newBuilder().initialCapacity(100).maximumSize(10_000).build();}@Beanpublic Cache<Long, ItemStock> stockCache(){return Caffeine.newBuilder().initialCapacity(100).maximumSize(10_000).build();}
}

然后,修改item-service中的com.heima.item.web包下的ItemController類,添加緩存邏輯:

@RestController
@RequestMapping("item")
public class ItemController {@Autowiredprivate IItemService itemService;@Autowiredprivate IItemStockService stockService;@Autowiredprivate Cache<Long, Item> itemCache;@Autowiredprivate Cache<Long, ItemStock> stockCache;// ...其它略@GetMapping("/{id}")public Item findById(@PathVariable("id") Long id) {return itemCache.get(id, key -> itemService.query().ne("status", 3).eq("id", key).one());}@GetMapping("/stock/{id}")public ItemStock findStockById(@PathVariable("id") Long id) {return stockCache.get(id, key -> stockService.getById(key));}
}

3.Lua語法入門

Nginx編程需要用到Lua語言,因此我們必須先入門Lua的基本語法。

3.1.初識Lua

Lua 是一種輕量小巧的腳本語言,用標準C語言編寫并以源代碼形式開放, 其設計目的是為了嵌入應用程序中,從而為應用程序提供靈活的擴展和定制功能。官網:https://www.lua.org/

3.1.HelloWorld

CentOS7默認已經安裝了Lua語言環境,所以可以直接運行Lua代碼。

1)在Linux虛擬機的任意目錄下,新建一個hello.lua文件
在這里插入圖片描述

2)添加下面的內容

print("Hello World!")  

3)運行
在這里插入圖片描述

3.2.變量和循環

3.2.1.Lua的數據類型

Lua中支持的常見數據類型包括:
在這里插入圖片描述

另外,Lua提供了type()函數來判斷一個變量的數據類型:
在這里插入圖片描述

3.2.2.聲明變量

Lua聲明變量的時候無需指定數據類型,而是用local來聲明變量為局部變量:

-- 聲明字符串,可以用單引號或雙引號,
local str = 'hello'
-- 字符串拼接可以使用 ..
local str2 = 'hello' .. 'world'
-- 聲明數字
local num = 21
-- 聲明布爾類型
local flag = true

Lua中的table類型既可以作為數組,又可以作為Java中的map來使用。數組就是特殊的table,key是數組角標而已:

-- 聲明數組 ,key為角標的 table
local arr = {'java', 'python', 'lua'}
-- 聲明table,類似java的map
local map =  {name='Jack', age=21}

Lua中的數組角標是從1開始,訪問的時候與Java中類似:

-- 訪問數組,lua數組的角標從1開始
print(arr[1])

Lua中的table可以用key來訪問:

-- 訪問table
print(map['name'])
print(map.name)

3.2.3.循環

對于table,我們可以利用for循環來遍歷。不過數組和普通table遍歷略有差異。

遍歷數組:

-- 聲明數組 key為索引的 table
local arr = {'java', 'python', 'lua'}
-- 遍歷數組
for index,value in ipairs(arr) doprint(index, value) 
end

遍歷普通table

-- 聲明map,也就是table
local map = {name='Jack', age=21}
-- 遍歷table
for key,value in pairs(map) doprint(key, value) 
end

3.3.條件控制、函數

Lua中的條件控制和函數聲明與Java類似。

3.3.1.函數

定義函數的語法:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/41275.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41275.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41275.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

卷積操作后特征圖尺寸,感受野,參數量的計算

文章目錄 1、輸出特征圖的尺寸大小2、感受野的計算3、卷積核的參數量 1、輸出特征圖的尺寸大小 如果包含空洞卷積&#xff0c;即擴張率dilation rate不為1時&#xff1a; 2、感受野的計算 例如&#xff0c;圖像經過兩個3*3&#xff0c;步長為2的卷積后感受野為&#xff1a; co…

Centos7多臺服務器免密登錄

準備四臺服務器: docker0 docker1 docker2 docker3 在docker0服務器上生成公鑰和私鑰 [rootwww ~]# ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Created directory /root/.ssh. Enter passp…

在Gazebo中添加懸浮模型后,利用鍵盤控制其移動方法

前段時間寫了文章&#xff0c;通過修改sdf、urdf模型的方法&#xff0c;在Gazebo中添加懸浮模型方法 / Gazebo中模型如何不因重力下落&#xff1a;在Gazebo中添加懸浮模型方法 / Gazebo中模型如何不因重力下落&#xff1a;修改sdf、urdf模型_sagima_sdu的博客-CSDN博客 今天講…

Leetcode32 最長有效括號

給你一個只包含 ( 和 ) 的字符串&#xff0c;找出最長有效&#xff08;格式正確且連續&#xff09;括號子串的長度。 代碼如下&#xff1a; class Solution {public int longestValidParentheses(String str) {Stack<Integer> s new Stack<>();int res 0;int st…

GrapeCity Documents for Excel, Java Edition Crack

GrapeCity Documents for Excel, Java Edition Crack 增加了對SpreadJS.sjs文件格式的支持&#xff1a; 更快地將大型Microsoft Excel文件轉換為.sjs格式。 使用較小的占用空間保存導出的文件。 將Excel/SpreadJS功能導入SpreadJS/從SpreadJS導出。 從.sjs文件中壓縮的JSON文件…

JVM——JDK 監控和故障處理工具總結

文章目錄 JDK 命令行工具jps:查看所有 Java 進程jstat: 監視虛擬機各種運行狀態信息 jinfo: 實時地查看和調整虛擬機各項參數jmap:生成堆轉儲快照**jhat**: 分析 heapdump 文件**jstack** :生成虛擬機當前時刻的線程快照 JDK 可視化分析工具JConsole:Java 監視與管理控制臺連接…

手撕單鏈表

目錄 鏈表的概念和結構 單鏈表的實現 申請新結點 打印 尾插 頭插 尾刪 頭刪 ?編輯 查找 在pos位置前插入元素 在pos位置后插入元素 刪除pos位置的元素 刪除pos位置之后的位置的元素?編輯 完整代碼 SListNode.h SListNode.c 鏈表的概念和結構 鏈表是一種物理存儲…

【JavaSE】Java方法的使用

【本節目標】 1. 掌握方法的定義以及使用 2. 掌握方法傳參 3. 掌握方法重載 4. 掌握遞歸 目錄 1.方法概念及使用 1.1什么是方法(method) 1.2 方法定義 1.3 方法調用的執行過程 1.4 實參和形參的關系 2. 方法重載 2.1 為什么需要方法重載 2.2 方法重載概念 3. 遞歸 3.…

【uni-app報錯】獲取用戶收貨地址uni.chooseAddress()報錯問題

chooseAddress:fail the api need to be declared in …e requiredPrivateInf 原因&#xff1a; 小程序配置 / 全局配置 (qq.com) 解決&#xff1a; 登錄小程序后臺申請接口 按照流程申請即可 在項目根目錄中找到 manifest.json 文件&#xff0c;在左側導航欄選擇源碼視圖&a…

杭電比賽總結

我們的隊伍&#xff1a;team013 另外兩隊&#xff1a;team014、team015 ? 今天是我第一次打杭電&#xff0c;發現杭電多數都是猜結論題 先給一下我們的提交數據 Submit TimeProblem IDTimeMemoryJudge Status4:59:59101115 MS1692 KWrong Answer4:59:55101115 MS1684 KWrong…

Java算法_ 檢查對稱樹(LeetCode_Hot100)

題目描述&#xff1a;給你一個二叉樹的根節點 &#xff0c; 檢查它是否軸對稱。root 獲得更多&#xff1f;算法思路:代碼文檔&#xff0c;算法解析的私得。 運行效果 完整代碼 /*** 2 * Author: LJJ* 3 * Date: 2023/8/17 8:47* 4*/ public class SymmetricTree {static class…

vue之動態表單(優化)

代碼資源在這兒 ↑ vue之動態表單優化 vue2js動態表單優化vue3ts動態表單優化 vue2js動態表單優化 效果圖 目錄結構 五個文件的完整代碼: 以下是App.vue <template><div><router-view></router-view><Formpage /></div> </templa…

【LeetCode】647.回文子串

題目 給你一個字符串 s &#xff0c;請你統計并返回這個字符串中 回文子串 的數目。 回文字符串 是正著讀和倒過來讀一樣的字符串。 子字符串 是字符串中的由連續字符組成的一個序列。 具有不同開始位置或結束位置的子串&#xff0c;即使是由相同的字符組成&#xff0c;也會…

web連接桌面打開gptmap

一&#xff1a;環境配置 需要的材料&#xff1a; python-3.10.4 我使用的是這個版本的&#xff0c;3.8.10 該版本和以下版本組件組合&#xff0c;驗證過能正常運行&#xff08;python 3.6.8測試異常&#xff09; websockify 該項目有python版本和node js版本 noVNC 形式的app…

Qt Designer設計的界面如何顯示、即運行顯示窗口界面

首先利用Qt Designer設計.ui文件&#xff0c;然后采用Tools->External Tools->PyUIC轉換成.py文件。這個.py文件是.ui文件編譯而來的&#xff0c;將這種文件由.ui文件編譯而來的.py文件稱之為界面文件。由于界面文件每次編譯時候都會初始化&#xff0c;所以需要新建一個.…

Android 13 添加自定義分區,恢復出廠設置不被清除

需求: 客戶有些文件或數據,需要做得恢復出廠設置還存在,故需新增一個分區存儲客戶數據。 要求: a) 分區大小為50M b) 應用層可讀可寫 c) 恢復出廠設置后不會被清除 d) 不需要打包.img e) 不影響OTA升級 缺點: 1).通過代碼在分區創建目錄和文件,會涉及到SeLinux權限的修…

● 123.買賣股票的最佳時機III ● 188.買賣股票的最佳時機IV

123.買賣股票的最佳時機III class Solution { public:int maxProfit(vector<int>& prices) {vector<vector<int>>dp(prices.size(),vector<int>(5));int lenprices.size();if(len0)return 0;dp[0][0]0;dp[0][1]-prices[0];dp[0][2]0;dp[0][3]-pr…

LeetCode150道面試經典題-- 環形鏈表(簡單)

1.題目 給你一個鏈表的頭節點 head &#xff0c;判斷鏈表中是否有環。 如果鏈表中有某個節點&#xff0c;可以通過連續跟蹤 next 指針再次到達&#xff0c;則鏈表中存在環。 為了表示給定鏈表中的環&#xff0c;評測系統內部使用整數 pos 來表示鏈表尾連接到鏈表中的位置&…

Java設計模式 (一) 模板方法設計模式

什么是模板方法設計模式? 模板方法設計模式是一種行為型設計模式&#xff0c;它定義了一個算法的骨架&#xff0c;并將一些步驟的具體實現延遲到子類中。模板方法模式可以幫助確保在算法的不同部分中保持一致性&#xff0c;同時也允許子類根據需要進行具體實現。 模板方法模式…

分布式光伏運維平臺在公益場館屋頂光伏發電系統的應用分析

摘要&#xff1a;2021年9月&#xff0c;國家發改委印發烷善能源消費強度和總量雙控制度方案》&#xff0c;提出鼓勵可再生能源的使用&#xff0c;支持可再生能源發展。在這樣的政策推動下&#xff0c;光伏發電市場無疑將迎來高質量發展的新機遇。現結合山東博物館光伏電站日常管…