《目錄》
---------->緩存的需要,緩存的原理
---------->頁面緩存的思路
---------->熱點數據緩存的思路,4個點
---------->頁面局部緩存(與靜態緩存的信息是相似的)
---------->緩存可能引起的問題以及解決思路
---------->由於后端跳轉頁面轉向ajax技術請求參數的頁面靜態化技術與思路,這一步也是前后端分離的實現
---------->SpringBoot的設置使得靜態頁面緩存在瀏覽器,與瀏覽器的基本查看
一、為什么要使用頁面緩存技術?
系統都是逐漸演進的,一個系統在運行中必須是根據場景逐漸地提高優化性能。高並發就是對資源的節約的考驗,這種考驗除了更換優秀和先進的技術,優化架構,還在於從小處出發,對盡可能節約的資源進行節約。而在一個系統的數據訪問中,系統的瓶頸往往是來自於數據庫,因此我們要盡可能減少對數據庫的訪問!在不影響用戶體驗的情況下,對於一些靜態或者變化不大的頁面,我們使用緩存來減少對數據庫的訪問!
二、緩存技術的原理?
我們都知道在一個請求中,邏輯越復雜,調用,依賴,訪問數據庫的越多,耗時也就越長,響應時間也就越長,性能也就越差!因此降低邏輯復雜度,減低耦合,提高內聚,減少數據庫訪問,將頻繁用到的變化不大的數據給緩存起來也就成為了提高性能的主要核心。
1.頁面緩存思路:
首先我們需要明白,一個頁面是從后端提高數據后,交給springMvc或者SpringBoot進行渲染,主要的頁面消耗是在渲染這部分。因此我們需要在這之前進行攔截。(針對於依靠后端進行頁面跳轉和渲染的緩存初始階段)
核心通用邏輯:當客戶的請求到達后端時,先去redis中查詢緩存,如果緩存中找不到,則進行數據庫邏輯操作,然后渲染,存入緩存並返回給前端!如果在緩存中找到了則直接返回給前端。存儲在Redis緩存中的頁面需要設置超時時間,緩存的時間長度根據頁面數據變化頻繁程度適當調整!目前大多數頁面緩存都是在60~120秒,少數幾乎不變化的可以調整到5分鍾!
2.熱點數據緩存思路:
所謂熱點數據,就是指在某段時間內被頻繁使用的對象數據。比如用戶登錄信息,用戶在登錄后,每次訪問都會攜帶其cookie信息進入后端,當信息到達后端后,其cookie信息就是我們存在redis中的key值。在這一步我們會做四個操作,並且在某些時候可使用攔截器進行處理:
<1>當用戶操作進來的時候,我們獲取到Cookie值並在Redis中查找,找到用戶信息則刷新用戶的登錄時間並允許用戶通過,找不到用戶信息則拒絕用戶繼續往下!,在后面的數據操作中,如果存在需要使用用戶信息的操作,則去Redis中查找,如果存在則允許操作!
<2>對於熱點數據源,被高頻訪問的不缺分權限信息的熱點數據,則設置全局緩存,定時更新則緩存數據,當有操作到此類的熱點數據緩存則主動更新緩存中的信息,將用戶攔截在數據之外!
<3>當涉及到用戶登錄的熱點數據被更新后,需要根據用戶的token作為key值重新寫入或者強制用戶重新登錄!
<4>對於需要頻繁更新的數據或寫入數據的數據,比如點贊次數,在線人數,可以設置一個層級,在沒有達到層級前寫在緩存中,每次只更新緩存則可以,當到一定次數則寫入數據庫!
2.頁面局部緩存:
熱點數據緩存,頁面靜態化進行ajax請求信息更新,此類信息一般都是比較頻繁發生變化的,涉及的可能是需要保存在數據庫的操作,類似表格信息,即時刷新的數據等!如果是屬於查看類的並且前端大量請求,可以經由於后端監控,定時寫入緩存!
核心通用邏輯:一般情況下封裝以類名--對象名為組合的字符串作為Redis的Key值,然后存入數據庫,每次訪問到目標的方法都先去緩存讀取,然后再處理!
三、緩存雪崩-數據穿透問題:
緩存雪崩:緩存雪崩是指因為數據未加載到緩存中,或者緩存同一時間大面積的失效,在某一時刻大量的緩存沒有命中,從而導致所有請求都去查數據庫,導致數據庫CPU和內存負載過高,甚至宕機!
- 緩存穿透:查詢一個數據庫必然不存在的數據,那么緩存里面也沒有。比如文章表中查詢一個不存在的id,每次都會訪問DB,如果有人惡意破壞,發送高頻請求,那么很可能直接對DB造成影響。
解決辦法:對所有可能查詢的參數以hash形式存儲,在控制層先進行校驗,不符合則丟棄。或者對於查詢為空的字段,設置一個默認值在緩存中,如果查詢到則返回默認值! 或者使用具備特點的key值,如果不符合則經由於系統過濾掉,不進入緩存也不進入數據庫,此做法可以降低一定的壓力,但是解決不了根本的問題。
2.緩存失效:如果緩存集中在一段時間內失效,DB的壓力凸顯,DB負載急劇上升。這個沒有完美解決辦法,但可以分析用戶行為,盡量讓失效時間點均勻分布。
3.緩存預熱:系統部署時,防止用戶一瞬間訪問數據庫,負載過大,由開發人員主動將數據加載到緩存中!
單機---系統:手動刷新頁面既可以了,或者定時緩存緩存
分布式系統: 分布式系統問題在於數據量非常大,緩存可能會導致數據庫宕機!通過程序進行單個緩存加載!
四、Redis頁面緩存實現
1.請求到來后,先調用根據key值去redis訪問,找到則返回
2.SpringBoot的redis中找不到調用webConext()對象進行加載
-
將Thyemleaf的thymeleafViewResolver給注入到Controller中
-
進行頁面渲染:
WebContext ctx=new
WebContext(request,response,request.getServletContext(),request.getLocale(),model.asMap());
html=thymeleafViewResolver.getTemplateEngine().process("頁面名稱無后綴",ctx);
- 返回頁面信息
================================================================================================
方法的返回以String對象,並且頁面不可以使用ResController作為注解(以json返回),頁面的reqestMapper里
設置:
@RequestMapping(value = "/xxxx",produces ="text/html")//可能沒有數據
@ResponseBody
3.SpringMvc的redis中使用攔截器或者過濾器用ModelAndView渲染,攔截器的用法過於簡單,自行百度,不做解釋
五、頁面靜態化?
除了將頁面資源與數據進行緩存以減少數據庫訪問外,還可以利用瀏覽器特點,將頁面給完全緩存在瀏覽器中,等到瀏覽器過時,再訪問項目,項目的請求經過項目內部緩存,緩存如果過時,再訪問數據庫!
將頁面靜態化的特點必須解決頁面如何獲取與處理數據,如何跳轉頁面的問題!在此我們可以參考 ajax技術 ,將請求與頁面完全獨立,保證頁面是靜態頁面,而請求通過Ajax技術局部刷新與全局刷新的特點來實現!變化如下:
1----原流程?
2----靜態化頁面流程?
注意:此流程為頁面靜態化的流程,前端的頁面跳轉將由頁面之間直接完成,不在通過后端!頁面之間的數據加載,則是通過Ajax請求的形式,請求后端返回JSON數據流。在請求中有緩存則顯訪問緩存,沒有緩存或者緩存超時則直接訪問下一層,知道完整返回數據!
3------瀏覽器設置與分析?
一般情況下,一個正常的請求都具備了請求報文和響應報文,請求和響應均分成三個部分,請求頭則維護了請求協議類型,而請求和響應報文則維護了對於報文體的參數,生命,來源等信息!第三部分則是本次請求的內容,也就是我們說的報文體!對於瀏覽器來說,他更像是一個負責頁面渲染和參數設定的容器,讀取報文頭的信息對報問題進行相關的操作,並通過一定的通過規則展示給使用者!
瀏覽器的主要功能是將用戶選擇的web資源呈現出來,它需要從服務器請求資源,並將其顯示在瀏覽器窗口中,資源的格式通常是HTML,也包括PDF、image及其他格式。 HTML和CSS規范中規定了瀏覽器解釋html文檔的方式,由W3C組織對這些規范進行維護,W3C是負責制定web標准的組織。
關於瀏覽器原理可以參考:https://kb.cnblogs.com/page/129756/
頁面靜態化的一個特點也是可以將靜態頁面給緩存在用戶瀏覽器一端。同一個頁面,在頁面的生命周期沒到之前,用戶的請求都是在本地進行(304);
用於識別是否緩存並且區分緩存時間的主要是以下三個模塊:
Pragma:支持http1.0版本的緩存
Expire:http2.0可以用,也向下兼容http1.0版本,16進制的字符串,以格里尼治時間也准,以服務端時間來定義緩存你是否超時,但由於客戶端與服務端緩存時間經常不一致,所以容易造成緩存失效!
Cache-control:Http版本1.0-2.0都可以用,以秒為單位,並且可以指定緩存為多少秒,對緩存時間進行倒計時,同時不會根據客戶端時間來衡量,也不會根據服務端時間衡量,完全依賴信息本身!
cache-control=max-age=3600:服務端告訴瀏覽器指定3600秒
觀察:在網絡XHR上面的連接輸出字段可以看到連接已經緩存,在緩存有效期內,每一次請求都是返回304,但只是瀏覽器自己處理,實際請求並沒有到達后端系統!
在springBoot后端的application.yml做如下設置:
resources:
add-mappings: true #配置
chain:
cache: true
enabled: true
gzipped: true#是否執行壓縮
html-application-cache: true #是否啟動html引用的緩存
static-locations: classpath:/static/ #靜態資源頁面的位置
cache-period: 3600 #頁面瀏覽器的配置緩存多少秒
============================================================================================
將該信息放置於spring的節點下
4-----靜態資源優化?
除了對靜態頁面優化,我們還可以通過一些方式減少流量,提供訪問的速度!當用戶的請求越小,性能也就相對越好!
1.JS/CSS壓縮,靜態資源盡量使用壓縮版的庫和包,以減少瀏覽器加載和請求的流量
2. 多個js/css組合到一個請求,減少連接數(正常30個,從服務端獲取,多次訪問,通過http獲取),把多個文件通過一個js/css一次性請求下來 配置 tengine模塊實現!
3.將多個Js/css的請求合並為一個
4.CDN:內容分發網絡,將數據緩存到網絡節點上,用戶請求來根據位置定向訪問到距離最近的節點,可用於解決網絡擁擠,跟代碼層面關系不是很大,在請求沒到網站之前,CDN會根據客戶的位置將請求分發到就近地網路節點上,如果節點有則直接返回!
注意:tengine與nginx的功能基本是一樣的,繼承了nginx所有特性,並且擁有可以對靜態資源壓縮合並請求等功能,詳情可參考tengine.taobaoorg ,可以參照Nginx的方式來配置Tengine!
六--------對於緩存?
對於一個項目來說,其瓶頸往往是在於數據庫的瓶頸。除了業務代碼的穩定性,我們所做的操作目的都是在減少數據庫的壓力。通過Redis頁面緩存,通過瀏覽器緩存,通過頁面靜態化,通過Redis頁面靜態緩存,通過Redis熱點數據緩存,Nginx緩存,Tengine緩存,CDN緩存等,層層攔截,以減少對數據庫的訪問!
但是對於數據來說,一切的緩存都是建立在不影響客戶體驗的基礎上,緩存因為其特點,仍熱存在着數據不同步的問題!
針對這個問題,能處理的只有?
定時刷新緩存,存儲變化非常小的頁面信息!
主動監控更新緩存!
————————————————
版權聲明:本文為CSDN博主「瓊歌」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_36505948/article/details/82620908