緩存又掛了?內(nèi)存又爆了?只需要一招完美解決!
O!NO!緩存又掛了,redis不給力?。话盐胰?,內(nèi)存爆了?DBA干啥去了,怎么老是掛???
你的緩存是不是經(jīng)常爆掉呢?是不是討厭DBA經(jīng)常叨叨叨的?跟唐僧一個樣?如果是,那么可能是你還沒玩會redis哦,為什么?因為緩存是用來對抗高并發(fā)熱點數(shù)據(jù)請求的,而你可能將大量的長時間不使用的數(shù)據(jù)也放在里面了,白白浪費了內(nèi)存。
今天教你一招,解決大量冷點數(shù)據(jù)白白浪費內(nèi)存。
Redis中有個設(shè)置時間過期的功能,即對存儲在redis數(shù)據(jù)庫中的值可以設(shè)置一個過期時間。作為一個緩存數(shù)據(jù)庫,這是非常實用的。然而很多的程序員并沒有認識到這一點,比如我們要緩存用戶的token,那么是不是你會將所有的都放入緩存?是的,然后問題是,下次又想緩存用戶登錄賬號和密碼加密串,又放入緩存,如果你有1000萬用戶,是不是發(fā)現(xiàn)內(nèi)存不夠了?
那么我們有必要將所有用戶的token都一直保存在內(nèi)存中嗎?
答案顯然不是,我們只需要緩存最近經(jīng)常用的。那些1、2年都不登錄一次的,顯然放mysql更經(jīng)濟實惠。
那問題又來了,我怎么知道用戶什么時候登錄?
是的,不知道,所以用戶注冊之后,我們需要放進入,但是如果用戶1個月沒有登錄,我們就可以刪除了,釋放內(nèi)存。
哦。OK,我知道了,我寫個定時任務(wù),自動去判斷就是了。
NO,NO,NO,根本用不著,redis已經(jīng)給你解決方案了。那就是過期時間。只需要寫入key的時候,設(shè)置好過期時間即可,剩下的交給redis。
如我們一般項目中的token或者一些登錄信息,尤其是短信驗證碼都是有時間限制的。這正是它的用武之地。

有效時間設(shè)置:
redis對存儲值的過期處理實際上是針對該值的鍵(key)處理的,即時間的設(shè)置也是設(shè)置key的有效時間。Expires字典保存了所有鍵的過期時間,Expires也被稱為過期字段。
redis> SET key va1ue
OK
redis> EXPlRE key 1000
(integer) 1
四種處理策略
1. EXPIRE 將key的生存時間設(shè)置為ttl秒
2. PEXPIRE 將key的生成時間設(shè)置為ttl毫秒
3. EXPIREAT 將key的過期時間設(shè)置為timestamp所代表的的秒數(shù)的時間戳
4. PEXPIREAT 將key的過期時間設(shè)置為timestamp所代表的的毫秒數(shù)的時間戳
其實以上幾種處理方式都是根據(jù)PEXPIREAT來實現(xiàn)的,設(shè)置生存時間的時候是redis內(nèi)部計算好時間之后在內(nèi)存處理的,最終的處理都會轉(zhuǎn)向PEXPIREAT。 1、2兩種方式是設(shè)置一個過期的時間段,就是咱們處理驗證碼最常用的策略,設(shè)置三分鐘或五分鐘后失效,把分鐘數(shù)轉(zhuǎn)換成秒或毫秒存儲到redis中。 3、4兩種方式是指定一個過期的時間 ,比如優(yōu)惠券的過期時間是某年某月某日,只是單位不一樣。
過期處理
過期鍵的處理就是把過期鍵刪除,這里的操作主要是針對過期字段處理的。 Redis中有三種處理策略:定時刪除、惰性刪除和定期刪除。
1. 定時刪除:在設(shè)置鍵的過期時間的時候創(chuàng)建一個定時器,當(dāng)過期時間到的時候立馬執(zhí)行刪除操作。不過這種處理方式是即時的,不管這個時間內(nèi)有多少過期鍵,不管服務(wù)器現(xiàn)在的運行狀況,都會立馬執(zhí)行,所以對CPU不是很友好。因此,請注意,不要將大量的key過期時間設(shè)置到同一時間,因為同一時間刪除操作,將消耗大量資源,可能導(dǎo)致線上redis不穩(wěn)定,甚至crash。
2. 惰性刪除:惰性刪除策略不會在鍵過期的時候立馬刪除,而是當(dāng)外部指令獲取這個鍵的時候才會主動刪除。處理過程為:接收get執(zhí)行、判斷是否過期(這里按過期判斷)、執(zhí)行刪除操作、返回nil(空)。這種策略需要注意,因為可能會導(dǎo)致內(nèi)存大量最近很少使用的key,占據(jù)內(nèi)存,很少使用,則這個key沒有訪問,也就不會刪除,還是占著內(nèi)存。
3. 定期刪除:這個一般是線上推薦方式,定期刪除是設(shè)置一個時間間隔,每個時間段都會檢測是否有過期鍵,如果有執(zhí)行刪除操作。同時也要注意,不要將大量的key過期時間設(shè)置為同一時間,同1策略類似。沒有2策略的問題。
看完上面三種策略后可以得出以下結(jié)論: (1) 1、3為主動刪除,2為被動刪除。 (2) 1是實時執(zhí)行的,線上慎重使用。(3) 2、3為被動刪除,所以過期鍵應(yīng)該會存在一定的時間,這樣就使得過期鍵不會被立馬刪除,仍然占用著內(nèi)存。但是惰性刪除的時候一般是單個刪除,相對來說對線上業(yè)務(wù)基本沒有影響。(4)定期刪除執(zhí)行不能過于頻繁,否則就可能會演變成定時刪除,如果執(zhí)行的過少就有可能造成過多過期鍵未被刪除而占用過多內(nèi)存。因此應(yīng)該根據(jù)線上情況進行合理設(shè)置。
持久化與復(fù)制的影響
過期鍵刪除策略對持久化以及復(fù)制的影響大致如下。
RDB: 1. 主服務(wù)器模式運行在載入RDB文件時,程序會檢查文件中的鍵,只會加載未過期的,過期的會被忽略,所以RDB模式下過期鍵不會對主服務(wù)器產(chǎn)生影響。 2. 從服務(wù)器運行載入RDB文件時,會載入所有鍵,包括過期和未過期。當(dāng)主服務(wù)器進行數(shù)據(jù)同步的時候,從服務(wù)器的數(shù)據(jù)會被清空,所以RDB文件的過期鍵一般不會對從服務(wù)器產(chǎn)生影響。
AOF: AOF文件不會受過期鍵的影響。如果有過期鍵未被刪除,會執(zhí)行以下動作: 客戶端請求時(過期鍵):
1. 從數(shù)據(jù)庫充刪除被訪問的過期鍵;
2. 追加一條DEL 命令到AOF文件;
3. 向執(zhí)行請求的客戶端回復(fù)nil(空)。
復(fù)制:
1. 主服務(wù)器刪除過期鍵之后,向從服務(wù)器發(fā)送一條DEL指令,告知刪除該過期鍵。
2. 從服務(wù)器接收到get指令的時候不會對過期鍵進行處理,只會當(dāng)做未過期鍵一樣返回。(為了保持主從服務(wù)器數(shù)據(jù)的一致性)
3. 從服務(wù)器只有接到主服務(wù)器發(fā)送的DEL指令后才會刪除過期鍵。
清理內(nèi)存全局策略
當(dāng)前已用內(nèi)存超過maxmemory限定時,將觸發(fā)主動清理策略。因為內(nèi)存已經(jīng)使用完了,然而緩存的數(shù)據(jù)中,可能存在一些長時間沒有使用的數(shù)據(jù),這時候我們可以根據(jù)一定的策略,進行有選擇的刪除清理,以保障內(nèi)存中緩存的都盡可能是熱點數(shù)據(jù)。
volatile-lru:只對設(shè)置了過期時間的key進行LRU(默認值)因此采用這種策略的redis,請將所有key設(shè)置過期時間。一般線上我們也推薦設(shè)置過期時間。
allkeys-lru : 刪除lru算法的key,這種策略不區(qū)分是否設(shè)置過期時間,key是否過期,是判斷哪些是最近最少使用的,進行刪除,避免有的設(shè)置了過期時間,而有的沒有設(shè)置,永不過期。
volatile-random:隨機刪除即將過期key,隨機刪除,但只是刪除快要過期的當(dāng)中去隨機刪除。如果你沒有設(shè)置過期時間,則不會刪除。
allkeys-random:隨機刪除,這是類似volatile-random,不同的是,它不區(qū)分是否過期,對所有key有效。
volatile-ttl : 刪除即將過期的。這個策略,則不計算LRU原則,而是只判斷即將要過期的,如果沒有設(shè)置過期時間,則不會刪除。
noeviction : 永不過期,返回錯誤。如果你所有的key都設(shè)置的永不過期,那么你有000萬用戶登錄過,你的redis將會很快內(nèi)存用完。無法寫入的問題。線上杜絕全部都是永不過期。
Lru是什么?就是按照最近最少使用的原則,比如長時間沒有登錄過的用戶,就可以刪除它的key,下次登錄從數(shù)據(jù)庫讀取出來。因為redis大多在內(nèi)存操作,因此內(nèi)存是很寶貴的,一定是給最常用的進行緩存,也就是緩存熱點數(shù)據(jù)。
看完今天的內(nèi)容,是不是應(yīng)該理解一下數(shù)據(jù)庫管理的抱怨,數(shù)據(jù)庫被爆滿,內(nèi)存枯竭,其實很多都是我們程序?qū)懭霐?shù)據(jù)的時候,不配置過期時間,導(dǎo)致實際上存了大量不常用的數(shù)據(jù),而內(nèi)存經(jīng)常不夠用,或是內(nèi)存消耗過高。
尊敬的程序員朋友們,今天的小知識mark到了嗎?






























