掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
O!NO!緩存又掛了,redis不給力啊;哎喲我去,內(nèi)存爆了?DBA干啥去了,怎么老是掛啊?

創(chuàng)新互聯(lián)公司堅持“要么做到,要么別承諾”的工作理念,服務領(lǐng)域包括:網(wǎng)站建設、成都網(wǎng)站設計、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務,滿足客戶于互聯(lián)網(wǎng)時代的洛寧網(wǎng)站設計、移動媒體設計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡建設合作伙伴!
你的緩存是不是經(jīng)常爆掉呢?是不是討厭DBA經(jīng)常叨叨叨的?跟唐僧一個樣?如果是,那么可能是你還沒玩會redis哦,為什么?因為緩存是用來對抗高并發(fā)熱點數(shù)據(jù)請求的,而你可能將大量的長時間不使用的數(shù)據(jù)也放在里面了,白白浪費了內(nèi)存。
今天教你一招,解決大量冷點數(shù)據(jù)白白浪費內(nèi)存。
Redis中有個設置時間過期的功能,即對存儲在redis數(shù)據(jù)庫中的值可以設置一個過期時間。作為一個緩存數(shù)據(jù)庫,這是非常實用的。然而很多的程序員并沒有認識到這一點,比如我們要緩存用戶的token,那么是不是你會將所有的都放入緩存?是的,然后問題是,下次又想緩存用戶登錄賬號和密碼加密串,又放入緩存,如果你有1000萬用戶,是不是發(fā)現(xiàn)內(nèi)存不夠了?
那么我們有必要將所有用戶的token都一直保存在內(nèi)存中嗎?
答案顯然不是,我們只需要緩存最近經(jīng)常用的。那些1、2年都不登錄一次的,顯然放mysql更經(jīng)濟實惠。
那問題又來了,我怎么知道用戶什么時候登錄?
是的,不知道,所以用戶注冊之后,我們需要放進入,但是如果用戶1個月沒有登錄,我們就可以刪除了,釋放內(nèi)存。
哦。OK,我知道了,我寫個定時任務,自動去判斷就是了。
NO,NO,NO,根本用不著,redis已經(jīng)給你解決方案了。那就是過期時間。只需要寫入key的時候,設置好過期時間即可,剩下的交給redis。
如我們一般項目中的token或者一些登錄信息,尤其是短信驗證碼都是有時間限制的。這正是它的用武之地。
redis對存儲值的過期處理實際上是針對該值的鍵(key)處理的,即時間的設置也是設置key的有效時間。Expires字典保存了所有鍵的過期時間,Expires也被稱為過期字段。
redis> SET key va1ue
OK
redis> EXPlRE key 1000
(integer) 1
1. EXPIRE 將key的生存時間設置為ttl秒
2. PEXPIRE 將key的生成時間設置為ttl毫秒
3. EXPIREAT 將key的過期時間設置為timestamp所代表的的秒數(shù)的時間戳
4. PEXPIREAT 將key的過期時間設置為timestamp所代表的的毫秒數(shù)的時間戳
其實以上幾種處理方式都是根據(jù)PEXPIREAT來實現(xiàn)的,設置生存時間的時候是redis內(nèi)部計算好時間之后在內(nèi)存處理的,最終的處理都會轉(zhuǎn)向PEXPIREAT。 1、2兩種方式是設置一個過期的時間段,就是咱們處理驗證碼最常用的策略,設置三分鐘或五分鐘后失效,把分鐘數(shù)轉(zhuǎn)換成秒或毫秒存儲到redis中。 3、4兩種方式是指定一個過期的時間 ,比如優(yōu)惠券的過期時間是某年某月某日,只是單位不一樣。
過期鍵的處理就是把過期鍵刪除,這里的操作主要是針對過期字段處理的。 Redis中有三種處理策略:定時刪除、惰性刪除和定期刪除。
1. 定時刪除:在設置鍵的過期時間的時候創(chuàng)建一個定時器,當過期時間到的時候立馬執(zhí)行刪除操作。不過這種處理方式是即時的,不管這個時間內(nèi)有多少過期鍵,不管服務器現(xiàn)在的運行狀況,都會立馬執(zhí)行,所以對CPU不是很友好。因此,請注意,不要將大量的key過期時間設置到同一時間,因為同一時間刪除操作,將消耗大量資源,可能導致線上redis不穩(wěn)定,甚至crash。
2. 惰性刪除:惰性刪除策略不會在鍵過期的時候立馬刪除,而是當外部指令獲取這個鍵的時候才會主動刪除。處理過程為:接收get執(zhí)行、判斷是否過期(這里按過期判斷)、執(zhí)行刪除操作、返回nil(空)。這種策略需要注意,因為可能會導致內(nèi)存大量最近很少使用的key,占據(jù)內(nèi)存,很少使用,則這個key沒有訪問,也就不會刪除,還是占著內(nèi)存。
3. 定期刪除:這個一般是線上推薦方式,定期刪除是設置一個時間間隔,每個時間段都會檢測是否有過期鍵,如果有執(zhí)行刪除操作。同時也要注意,不要將大量的key過期時間設置為同一時間,同1策略類似。沒有2策略的問題。
看完上面三種策略后可以得出以下結(jié)論: (1) 1、3為主動刪除,2為被動刪除。 (2) 1是實時執(zhí)行的,線上慎重使用。(3) 2、3為被動刪除,所以過期鍵應該會存在一定的時間,這樣就使得過期鍵不會被立馬刪除,仍然占用著內(nèi)存。但是惰性刪除的時候一般是單個刪除,相對來說對線上業(yè)務基本沒有影響。(4)定期刪除執(zhí)行不能過于頻繁,否則就可能會演變成定時刪除,如果執(zhí)行的過少就有可能造成過多過期鍵未被刪除而占用過多內(nèi)存。因此應該根據(jù)線上情況進行合理設置。
過期鍵刪除策略對持久化以及復制的影響大致如下。
RDB: 1. 主服務器模式運行在載入RDB文件時,程序會檢查文件中的鍵,只會加載未過期的,過期的會被忽略,所以RDB模式下過期鍵不會對主服務器產(chǎn)生影響。 2. 從服務器運行載入RDB文件時,會載入所有鍵,包括過期和未過期。當主服務器進行數(shù)據(jù)同步的時候,從服務器的數(shù)據(jù)會被清空,所以RDB文件的過期鍵一般不會對從服務器產(chǎn)生影響。
AOF: AOF文件不會受過期鍵的影響。如果有過期鍵未被刪除,會執(zhí)行以下動作: 客戶端請求時(過期鍵):
1. 從數(shù)據(jù)庫充刪除被訪問的過期鍵;
2. 追加一條DEL 命令到AOF文件;
3. 向執(zhí)行請求的客戶端回復nil(空)。
復制:
1. 主服務器刪除過期鍵之后,向從服務器發(fā)送一條DEL指令,告知刪除該過期鍵。
2. 從服務器接收到get指令的時候不會對過期鍵進行處理,只會當做未過期鍵一樣返回。(為了保持主從服務器數(shù)據(jù)的一致性)
3. 從服務器只有接到主服務器發(fā)送的DEL指令后才會刪除過期鍵。
當前已用內(nèi)存超過maxmemory限定時,將觸發(fā)主動清理策略。因為內(nèi)存已經(jīng)使用完了,然而緩存的數(shù)據(jù)中,可能存在一些長時間沒有使用的數(shù)據(jù),這時候我們可以根據(jù)一定的策略,進行有選擇的刪除清理,以保障內(nèi)存中緩存的都盡可能是熱點數(shù)據(jù)。
volatile-lru:只對設置了過期時間的key進行LRU(默認值)因此采用這種策略的redis,請將所有key設置過期時間。一般線上我們也推薦設置過期時間。
allkeys-lru : 刪除lru算法的key,這種策略不區(qū)分是否設置過期時間,key是否過期,是判斷哪些是最近最少使用的,進行刪除,避免有的設置了過期時間,而有的沒有設置,永不過期。
volatile-random:隨機刪除即將過期key,隨機刪除,但只是刪除快要過期的當中去隨機刪除。如果你沒有設置過期時間,則不會刪除。
allkeys-random:隨機刪除,這是類似volatile-random,不同的是,它不區(qū)分是否過期,對所有key有效。
volatile-ttl : 刪除即將過期的。這個策略,則不計算LRU原則,而是只判斷即將要過期的,如果沒有設置過期時間,則不會刪除。
noeviction : 永不過期,返回錯誤。如果你所有的key都設置的永不過期,那么你有000萬用戶登錄過,你的redis將會很快內(nèi)存用完。無法寫入的問題。線上杜絕全部都是永不過期。
Lru是什么?就是按照最近最少使用的原則,比如長時間沒有登錄過的用戶,就可以刪除它的key,下次登錄從數(shù)據(jù)庫讀取出來。因為redis大多在內(nèi)存操作,因此內(nèi)存是很寶貴的,一定是給最常用的進行緩存,也就是緩存熱點數(shù)據(jù)。
看完今天的內(nèi)容,是不是應該理解一下數(shù)據(jù)庫管理的抱怨,數(shù)據(jù)庫被爆滿,內(nèi)存枯竭,其實很多都是我們程序?qū)懭霐?shù)據(jù)的時候,不配置過期時間,導致實際上存了大量不常用的數(shù)據(jù),而內(nèi)存經(jīng)常不夠用,或是內(nèi)存消耗過高。
尊敬的程序員朋友們,今天的小知識mark到了嗎?

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流