拒絕躺平,Redis選擇實(shí)現(xiàn)了自己的VM
點(diǎn)擊下方“IT牧場(chǎng)”,選擇“設(shè)為星標(biāo)”

codenong.com/cs106843764
Redis 源碼中有很多優(yōu)秀的實(shí)踐,值得我們學(xué)習(xí)。它作為開(kāi)源作品之一,匯聚了眾多開(kāi)源智慧,深受廣大程序員喜愛(ài)。它的優(yōu)秀還導(dǎo)致了不少人都喜歡研究它,面試官也喜歡提問(wèn)面試者,也使整個(gè)行業(yè)進(jìn)入了更深的內(nèi)卷。

我相信多數(shù)人還是拒絕選擇躺平的,今天我們一起來(lái)了解一下,Redis 的 VM 機(jī)制。
Redis 之 VM 機(jī)制
Redis 的 VM (虛擬內(nèi)存)機(jī)制就是暫時(shí)把不經(jīng)常訪(fǎng)問(wèn)的數(shù)據(jù)(冷數(shù)據(jù))從內(nèi)存交換到磁盤(pán)中,從而騰出寶貴的內(nèi)存空間用于其它需要訪(fǎng)問(wèn)的數(shù)據(jù)(熱數(shù)據(jù))。通過(guò) VM 功能可以實(shí)現(xiàn)冷熱數(shù)據(jù)分離,使熱數(shù)據(jù)仍在內(nèi)存中、冷數(shù)據(jù)保存到磁盤(pán)。這樣就可以避免因?yàn)閮?nèi)存不足而造成訪(fǎng)問(wèn)速度下降的問(wèn)題。Redis 提高數(shù)據(jù)庫(kù)容量的辦法有兩種:一種是可以將數(shù)據(jù)分割到多個(gè) Redis Server上;另一種是使用虛擬內(nèi)存把那些不經(jīng)常訪(fǎng)問(wèn)的數(shù)據(jù)交換到磁盤(pán)上。「需要特別注意的是 Redis 并沒(méi)有使用 OS 提供的 Swap,而是自己實(shí)現(xiàn)。」
Redis 為了保證查找的速度,只會(huì)將 value 交換出去,而在內(nèi)存中保留所有的 Key。所以它非常適合 Key 很小,Value 很大的存儲(chǔ)結(jié)構(gòu)。如果 Key 很大,value 很小,那么vm可能還是無(wú)法滿(mǎn)足需求。
VM 相關(guān)配置
通過(guò)在 redis 的 redis.conf 文件里,設(shè)置 VM 的相關(guān)參數(shù)來(lái)實(shí)現(xiàn)數(shù)據(jù)在內(nèi)存和磁盤(pán)之間 換入和 換出操作。相關(guān)配置如下:
#開(kāi)啟vm功能
vm-enabled yes
#交換出來(lái)的value保存的文件路徑
vm-swap-file /tmp/redis.swap
#設(shè)置當(dāng)內(nèi)存消耗達(dá)到上限時(shí)開(kāi)始將value交換出來(lái)
vm-max-memory 1000000
#設(shè)置單個(gè)頁(yè)面的大小,單位是字節(jié)
vm-page-size 32
#設(shè)置最多能交換保存多少個(gè)頁(yè)到磁盤(pán)
vm-pages 13417728
#設(shè)置完成交換動(dòng)作的工作線(xiàn)程數(shù),設(shè)置為0表示不使用工作線(xiàn)程而使用主線(xiàn)程,這會(huì)以阻塞的方式來(lái)運(yùn)行。建議設(shè)置成CPU核個(gè)數(shù)
vm-max-threads 4
redis 規(guī)定同一個(gè)數(shù)據(jù)頁(yè)面只能保存一個(gè)對(duì)象,但一個(gè)對(duì)象可以保存在多個(gè)數(shù)據(jù)頁(yè)面中。在 redis 使用的內(nèi)存沒(méi)超過(guò) vm-max-memory 時(shí),是不會(huì)交換任何 value 到磁盤(pán)上的。當(dāng)超過(guò)最大內(nèi)存限制后,redis 會(huì)選擇較老的對(duì)象(如果兩個(gè)對(duì)象一樣老會(huì)優(yōu)先交換比較大的對(duì)象)將它從內(nèi)存中移除,這樣會(huì)更加節(jié)約內(nèi)存。
對(duì)于 Redis 來(lái)說(shuō),一個(gè)數(shù)據(jù)頁(yè)面只會(huì)保存一個(gè)對(duì)象,也就是一個(gè) Value 值,所以應(yīng)該將 vm-page-size 設(shè)置成大多數(shù) value 可以保存進(jìn)去。如果設(shè)置太小,一個(gè) value 對(duì)象就會(huì)占用幾個(gè)數(shù)據(jù)頁(yè)面,如果設(shè)置太大,就會(huì)造成頁(yè)面空閑空間浪費(fèi)。
VM 的工作機(jī)制
redis 的 VM 的工作機(jī)制分為兩種:一種是 vm-max-threads=0,一種是 vm-max-threads > 0。
「第一種:vm-max-threads = 0」
數(shù)據(jù)換出:主線(xiàn)程定期檢查使用的內(nèi)存大小,如果發(fā)現(xiàn)內(nèi)存超出最大上限,會(huì)直接以阻塞的方式,將選中的對(duì)象 換出 到磁盤(pán)上(保存到文件中),并釋放對(duì)象占用的內(nèi)存,此過(guò)程會(huì)一直重復(fù)直到下面條件滿(mǎn)足任意一條才結(jié)束:內(nèi)存使用降到最大限制以下。 設(shè)置的交換文件數(shù)量達(dá)到上限。 幾乎全部的對(duì)象都被交換到磁盤(pán)了。 數(shù)據(jù)換入:當(dāng)有 client 請(qǐng)求 key 對(duì)應(yīng)的 value 已被換出到磁盤(pán)中時(shí),主線(xiàn)程會(huì)以阻塞的方式從換出文件中加載對(duì)應(yīng)的 value 對(duì)象,加載時(shí)此時(shí)會(huì)阻塞所有 client,然后再處理 client 的請(qǐng)求。「這種方式會(huì)阻塞所有的 client。」
「第二種:vm-max-threads > 0」
數(shù)據(jù)換出:當(dāng)主線(xiàn)程檢測(cè)到使用內(nèi)存超過(guò)最大上限,會(huì)將選中的要交換的數(shù)據(jù)放到一個(gè)隊(duì)列中交由工作線(xiàn)程后臺(tái)處理,主線(xiàn)程會(huì)繼續(xù)處理 client 請(qǐng)求。數(shù)據(jù)換入:當(dāng)有 client 請(qǐng)求 key 的對(duì)應(yīng)的 value 已被換出到磁盤(pán)中時(shí),主線(xiàn)程先阻塞當(dāng)前 client,然后將加載對(duì)象的信息放到一個(gè)隊(duì)列中,讓工作線(xiàn)程去加載,此時(shí)進(jìn)主線(xiàn)程繼續(xù)處理其他 client 請(qǐng)求。加載完畢后工作線(xiàn)程通知主線(xiàn)程,主線(xiàn)程再執(zhí)行被阻塞的 client 的命令。「這種方式只阻塞單個(gè) client。」
總結(jié)
Redis 直接自己構(gòu)建了 VM 機(jī)制 ,不會(huì)像一般的系統(tǒng)會(huì)調(diào)用系統(tǒng)函數(shù)處理,會(huì)浪費(fèi)一定的時(shí)間去 移動(dòng) 和 請(qǐng)求,而 Redis 不存在。這也是 Redis 能夠那么快的一個(gè)原因之一了。
干貨分享
最近將個(gè)人學(xué)習(xí)筆記整理成冊(cè),使用PDF分享。關(guān)注我,回復(fù)如下代碼,即可獲得百度盤(pán)地址,無(wú)套路領(lǐng)取!
?001:《Java并發(fā)與高并發(fā)解決方案》學(xué)習(xí)筆記;?002:《深入JVM內(nèi)核——原理、診斷與優(yōu)化》學(xué)習(xí)筆記;?003:《Java面試寶典》?004:《Docker開(kāi)源書(shū)》?005:《Kubernetes開(kāi)源書(shū)》?006:《DDD速成(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)速成)》?007:全部?008:加技術(shù)群討論
加個(gè)關(guān)注不迷路
喜歡就點(diǎn)個(gè)"在看"唄^_^
