<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          引入『客戶端緩存』,Redis6算是把緩存玩明白了…

          共 4561字,需瀏覽 10分鐘

           ·

          2022-05-12 22:32


          源?/?? ? ? ??文/?



          而今天要和大家分享的技術(shù),在思想上和之前提及的兩級緩存有些類似,不過不需要借助其他本地緩存中間件,只使用Redis自身服務端和客戶端就可以實現(xiàn)。這就是Redis6中的客戶端緩存Client-side caching這一項新特性,它允許將數(shù)據(jù)緩存在應用服務端以及遠程緩存兩個位置。

          簡介

          客戶端緩存是Redis6眾多新特性中比較實用的一項新功能,我們看看官方文檔,了解一下它的作用:

          客戶端緩存是一種用于創(chuàng)建高性能服務的技術(shù),它可以利用應用服務器上的可用內(nèi)存(這些服務器通常是一些不同于數(shù)據(jù)庫服務器的節(jié)點),在這些應用服務端來直接存儲數(shù)據(jù)庫中的一些信息。

          與訪問數(shù)據(jù)庫等網(wǎng)絡服務相比,訪問本地內(nèi)存所需要的時間消耗要少得多,因此這個模式可以大大縮短應用程序獲取數(shù)據(jù)的延遲,同時也能減輕數(shù)據(jù)庫的負載壓力。

          看到這,我心想這不是和其他本地緩存Guava、Caffeine啥的一樣嗎,換湯不換藥,都是使用的應用服務的內(nèi)存罷了。要說有什么好處,可能就是我在項目中能少引入一個中間件了。

          不過,我這點淺薄的猜想,在看完客戶端緩存的具體應用模式后,徹底被顛覆了。

          兩種模式

          在了解了客戶端緩存的基本功能后,我們來看看它的兩種基本應用模式。Redis的客戶端緩存支持被稱為tracking,個人感覺翻譯為對key的追蹤就很好理解,它具有兩種模式:

          • 默認模式,服務端會記錄某個客戶端具體訪問過哪一些key,當這些key對應的值發(fā)生變化時,會發(fā)送失效消息給這些客戶端。這個模式會在服務端消耗一些內(nèi)存,但是發(fā)送失效消息的范圍,被限制在了客戶端存儲了的key的集合范圍內(nèi)
          • 廣播模式,服務端不會再記錄某個客戶端訪問了哪些key,因此這個模式不消耗服務端的內(nèi)存。取而代之的是,客戶端需要訂閱key的特定前綴,每當符合這個前綴的key對應的值發(fā)生改變時,客戶端都會收到通知消息

          看到這里,它和我們之前使用的兩級緩存之間差異,是不是已經(jīng)初露端倪了呢?如果還不熟悉兩級緩存的架構(gòu),那么可以先來看看下面的這張圖:

          這種架構(gòu)在理論上看起來不錯,但是實際使用起來需要注意的點不少,尤其是在分布式模式下,需要保證各個主機下的一級緩存的一致性問題,回想一下我們原先的解決方案,可以使用redis本身的發(fā)布/訂閱功能來實現(xiàn):

          而客戶端緩存的出現(xiàn),大大簡化了這一過程。我們以默認模式為例,看一下使用了客戶端緩存后的操作過程:

          相比原先的發(fā)布/訂閱模式,我們可以看到明顯的優(yōu)勢,使用客戶端緩存功能后,我們只需要單純的修改redis中的數(shù)據(jù)就可以了,手動處理發(fā)布/訂閱消息的這一過程可以完全被省略。

          優(yōu)勢

          到這里,在了解了客戶端緩存的基本功能與兩種模式后,我們來對比一下,和傳統(tǒng)的只使用redis做遠程緩存、以及使用整合后的兩級緩存相比較,客戶端緩存具有什么樣的優(yōu)勢。

          • 當應用的服務端存在緩存時,會直接讀取本地緩存,能夠減少網(wǎng)絡訪問上造成的延遲,從而加快訪問速度
          • 同時也能減少訪問redis服務端的次數(shù),降低redis的負載壓力
          • 在分布式環(huán)境下,不再需要通過發(fā)布訂閱來通知其他主機更新本地緩存,來保證數(shù)據(jù)的一致性。使用客戶端緩存后,它所具有的原生的消息通知功能,能很好地支持作廢本地緩存,保證之后訪問時能取到更新后的新數(shù)據(jù)

          誤區(qū)

          在開始演示客戶端緩存的使用之前,我們先來糾正一個誤區(qū)。

          雖然這個新特性被稱為客戶端緩存,但是redis本身不提供在應用服務端緩存數(shù)據(jù)的功能,這個功能要由訪問redis的客戶端自己去實現(xiàn)。

          說白了,也就是redis服務端只負責通知你,你緩存在應用服務本地的這個key已經(jīng)作廢了,至于你本地如何緩存的這些數(shù)據(jù),redis并不關心,也不負責。

          功能演示

          下面將通過一些實例來進行演示,本文代碼的運行前提條件是你已經(jīng)裝好了Redis6.x版本,linux環(huán)境下可以直接從官網(wǎng)下載后編譯安裝,windows環(huán)境下的安裝可以參考?手摸手教你在Windows環(huán)境下運行Redis6.x?這篇文章。

          概念上的東西我們也大體了解了,下面我們分別來看一下客戶端緩存具體實現(xiàn)的三種模式(至于為什么多了一種,后面再來細說)。在正式開始前,強烈建議大家先花個十幾分鐘了解一下?Redis6底層的通信協(xié)議RESP3,否則在看到具體的通信內(nèi)容時可能會存在一些疑問。

          首先做一下準備工作,通過telnet連接redis服務,并切換到resp3協(xié)議模式:

          telnet?127.0.0.1?6379
          hello?3

          1、默認模式

          在使用客戶端連接到redis服務后,需要先通過指令開啟tracking模式的功能,因為在客戶端連接后這個選項是默認關閉的,會無法收到失效類型的push消息:

          #開啟
          client?tracking?on
          #關閉
          client?tracking?off

          當開啟tracking后的默認模式下,redis服務端會記錄每個客戶端請求過的key,當key對應的值發(fā)生變化時,會發(fā)送失效信息給客戶端。簡單總結(jié)一下,也就是說這個模式能夠生效的必要前提條件有兩個:

          • 開啟tracking
          • 客戶端訪問過某個key

          下面我們還是在telnet中來模擬一下這個過程,分別啟動兩個redis客戶端,在client1中先執(zhí)行get命令后,再在client2對相同的key執(zhí)行set操作修改它的值,之后就會在client1中收到push類型的消息。

          push類型的消息我們在RESP3中介紹過了,這里簡單再嘮叨兩句:

          >2
          $10
          invalidate
          *1
          $4
          user

          起始的第一字節(jié)>表示該消息為push類型,后面消息體中包含了兩部分內(nèi)容,第一部分表示收到的消息類型為invalidate,也就是作廢類型的信息,第二部分則是需要作廢的key是user。

          除此之外,當一個緩存的key到達失效時間導致過期,或是因為到達最大內(nèi)存,要使用驅(qū)逐策略進行驅(qū)逐時,也會對客戶端發(fā)送PUSH的消息。下面以緩存的key過期為例:

          另外,對于單個key來說,這個tracking消息只會對客戶端發(fā)送一次,當?shù)诙涡薷脑搆ey所對應的值后,客戶端不會再收到tracking的消息。只有對這個key再執(zhí)行一次get命令,之后才會再次收到tracking消息。

          默認模式雖然使用起來簡單,但是需要在服務端存儲客戶端的訪問數(shù)據(jù),記錄哪些key被哪些客戶端訪問過。如果訪問的不是少量的熱點數(shù)據(jù)的話,可能會占用大量redis服務端的內(nèi)存空間。應對這種情況,可以試一試下面要介紹的廣播模式。

          2、廣播模式

          在廣播模式BCAST下,redis服務端不再記錄key的訪問情況,而是無差別地向所有開啟tracking廣播的客戶端發(fā)送消息。這樣一來,好處就是不需要浪費redis服務端的內(nèi)存進行記錄,但是壞處就是客戶端可能會收到過多的消息,其中可能還會包含自己不需要的一些key。

          在使用前,需要先通過命令開啟廣播模式:

          client?tracking?on?bcast

          下面,我們通過一個例子來進行廣播模式的使用演示:

          可以看到在開啟廣播模式后,只要在client2中修改了key對應的值,在client1中都會收到作廢消息,而不管client1之前在本地是否進行過緩存。

          并且,另外一點和默認模式不同的是,廣播模式是能夠重復多次收到一個key的失效消息的,因為服務端沒有記錄,所以只要有key發(fā)生了修改,客戶端就會收到失效消息。

          這時候,有的小伙伴可能就要問了,如果我不想收到這么多沒用的冗余消息,有沒有什么辦法進行一下過濾或精簡呢?

          答案是可以的,在廣播模式下,客戶端可以只關注一些特定前綴的key,表示我只需要接收這些前綴的key,其他的就不要發(fā)給我了。命令格式如下:

          client?tracking?on?bcast?prefix?myprefix

          再來看一下使用過程的示例:

          可以看到,在設置了只關注以order:作為前綴的key后,成功過濾掉了user的失效消息。從這個角度來看,也要求了我們在緩存一個類型的數(shù)據(jù)時,都以相同的單詞作為前綴,規(guī)范了我們在使用緩存中對key的命名規(guī)則。

          至于在業(yè)務中具體要使用哪種模式,可能更多的需要進行一下權(quán)衡。看一下你究竟是能忍受占用更多redis服務端的內(nèi)存,還是能夠忍受收到大量不需要的失效消息。

          3、轉(zhuǎn)發(fā)模式

          默認模式和廣播模式的生效,都要在開啟RESP3協(xié)議的前提下,具體原因看過上面的例子大家應該也都清楚了,因為要使用tracking的話,就必須要借助到RESP3協(xié)議中的新的push消息類型。

          那么如果客戶端還是使用的舊版本RESP V2的話,也想要體驗這一功能,應該如何進行改造呢?

          不得不說redis6的開發(fā)者想的還是蠻全面的,為了適配RESP V2,專門設計了一種新的轉(zhuǎn)發(fā)模式,允許使用舊版本協(xié)議的客戶端通過Pub/Sub發(fā)布訂閱功能來接收key的失效信息。

          從上面這張圖可以看到,轉(zhuǎn)發(fā)模式的核心就是redis服務端會將原先push類型的tracking信息,轉(zhuǎn)發(fā)到訂閱了_redis_:invalidate這一信道的被指定的客戶端上。

          我們來梳理一下上面的流程,首先在client1需要使用指令開啟轉(zhuǎn)發(fā)模式:

          client?tracking?on?bcast?redirect?[client-id]

          相對廣播模式,多了兩個參數(shù),redirect表示為轉(zhuǎn)發(fā)模式,后面的client-id表示消息要發(fā)送給哪一個客戶端,客戶端的id可以在client2上通過client id指令獲取。

          在client2中,則需要訂閱指定的信道:

          subscribe?_redis_:invalidate

          其實說白了,轉(zhuǎn)發(fā)模式還是使用的發(fā)布訂閱功能罷了,只不過redis幫我們解放了雙手,把發(fā)送消息的工作由自己完成了。整個操作的流程如下圖所示:

          可以看到,client2中收到的消息格式與之前的push類型消息不同,是一條RESP V2中多條批量回復格式的消息,表示的含義同樣是收到的key已經(jīng)作廢掉了。

          需要注意的是,雖然說開啟轉(zhuǎn)發(fā)模式的指令中也帶了一個bcast,但是它和廣播模式有著非常大的區(qū)別。在轉(zhuǎn)發(fā)模式下,key的作廢消息只能被轉(zhuǎn)發(fā)到一個客戶端上,如果先后執(zhí)行兩條指定轉(zhuǎn)發(fā)指令,那么后執(zhí)行的指令會覆蓋前一指令中轉(zhuǎn)發(fā)的client-id。

          看到這里是不是多少感覺這個轉(zhuǎn)發(fā)模式有點雞肋,畢竟實際的業(yè)務場景中很有可能會有多個客戶端的存在,只能轉(zhuǎn)發(fā)一個實在是有點說不過去了。不過,也有可能作者就是這么設計,留點缺陷,好讓大家更快地擁抱RESP3……

          總結(jié)

          好啦,到這里客戶端緩存的基本理論和使用就介紹的差不多了,不得不說,Redis6的這個新特性確實給了我們眼前一亮的感覺。從這個新特性也可以看出,Redis大有把緩存從服務端的局限中掙脫出來,染指向客戶端,一統(tǒng)緩存江湖的意味。

          不過這個過程應該并不簡單,就像我們前面說的,畢竟只有Redis服務端還不夠,還需要優(yōu)秀的客戶端進行支持才行。

          那么下一篇文章,我們就來從實戰(zhàn)角度,看看如何改造客戶端,讓client-side caching能在項目中落地開花。



          end





          頂級程序員:topcoding

          做最好的程序員社區(qū):Java后端開發(fā)、Python、大數(shù)據(jù)、AI


          一鍵三連「分享」、「點贊」和「在看」



          瀏覽 53
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  熟妇xxxxxx | 亚州多毛少妇 | 骚逼看片 | 日批在线网站 | 日韩超清无码 |