redis常見問題

什麼是redis?

redis是一個基於內存的高性能key-value數據庫,全稱Remote Dictionary Server。

redis和memcached的區別?

1)持久化

memcached把數據全部存在內存中,斷電後會掛掉,數據不能超過內存大小

redis支持持久化,持久化的數據存在硬盤上

2)支持的數據類型

memchached支持的數據類型相對簡單,redis支持string、list、set、zset、hash

3)value大小

redis單個value最大可以達到1G,而memcached只有1MB

4)底層模型不同

他們之間底層實現方式以及與客戶端之間同行的應用協議不一樣。

redis直接自己構建了VM機制,因爲一般的系統調用系統函數的話,會浪費一定的時間移動和請求

redis爲什麼快?

基於內存,避免了磁盤I/O的瓶頸。

單進程單線程,減少了線程上下文切換的開銷。

利用隊列技術將並行訪問變爲串行訪問,消除了傳統數據庫併發訪問控制鎖的開銷。

redis全程使用hash結構,讀取速度快,還有一些

Redis內存數據集大小上升到一定大小的時候,就會實行數據淘汰策略(回收策略)。redis提供6種數據策略:

LRU最近最久未使用

 

volatile-lru:從已設置過期時間的數據集(sever.db[I].expires)中挑選最近最少使用的數據淘汰

volatile-ttl:從已設置過期時間的數據集(sever.db[I].expires)中挑選將要過期的數據淘汰

volatile-random:從已設置過期時間的數據集(sever.db[I].expires)中任意選擇數據淘汰

allkeys-lru:從數據集(server.db[I].dict)中挑選最近最少使用的數據淘汰

allkeys-random:從數據集(server.db[I].dict)中任意選擇數據淘汰

no-enviction:禁止驅逐數據

 

 

AOF vs RDB

RDB持久化是指在指定的時間間隔內將內存中的數據集快照寫入磁盤,實際操作過程是fork一個子進程,現將數據集寫入臨時文件,寫入成功後,在替換之前的文件,用二進制壓縮存儲

 

AOF持久化一日之的形式記錄服務器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文本的方式記錄,可以打開文件看到詳細的操作記錄。

 

RDB存在哪些優勢

1>靈活設置備份頻率和週期。你可能打算每個小時歸檔一次最近24小時的數據,同事還要每天歸檔一次最近30天的數據。通過這樣的備份策略,一旦系統出現災難性故障,我們可以非常容易的進行恢復

 

2>對於災難恢復而言,RDB是非常不錯的選擇。因爲我們可以非常輕鬆地講一個單獨的文件壓縮後再轉移到其他存儲介質上

 

3>性能最大化。對於redis的服務進程而言,在開始持久化時,他唯一需要做的只是fork出子進程,之後再由子進程完成這些持久化工作,這樣就可以極大地避免服務進程執行IO操作了。

 

4>相對於AOF機制,如果數據集很大,RDB的啓動效率會更高

 

RDB的缺點

1>如果你想保證數據的高可用性,即最大限度的避免數據丟失,那麼RDB將不是一個很好的選擇。因爲系統一旦在定是持久化之前出現宕機現象,此前沒有來得及寫入磁盤的數劇都將丟失。

 

2>由於RDB是通過fork子進程來協助完成數據持久化工作的,因此,如果當數據集較大時,可能會導致整個服務器停止服務幾百毫秒,甚至是1s

 

AOF的優勢

1>該機制可以代碼更高的數據安全性,即數據持久性。redis中提供了3種同步策略,即每秒同步、每修改同步和不同步。事實上,每秒同步也是一步完成的,其效率也是非常高的,所查的是一旦系統出現宕機現象,那麼這一秒之內修改的數據將會丟失,而沒修改同步,我們可以將其視爲同步持久化,即每次發生的數據變化都會被立即記錄到磁盤中。可以預見,這種方式在效率上市最低的。

 

2>由於該機制對日誌文件的寫入操作採用的是append模式,因此在寫入過程中及時出現當即現象,也不會破壞文件中已經存在的內容。然後如果我們本次操作知識寫入了一般數據就出現了系統崩潰問題,不用擔心,在redis下一次啓動之前,我們可以通過redis-check-aof工具來幫我們解決數據一致性的問題。

 

3>如果日誌過大,redis可以自動啓用rewrite機制。即redis以append模式不斷地將修改的數據寫入到老的磁盤文件中,同時,redis還會創建一個新的文件用於記錄此期間有哪些修改命令被執行。因此在進行rewrite切換時可以更好地保證數據安全性

 

4>AOF包含一個格式清晰,易於理解的日誌文件用於記錄所有的修改操作。事實上,我們也可以通過該文件完成數據的重建。

 

AOF不足

1>對於形同數量的數據集而言,AOF文件通常要大於RDB文件。RDB在恢復大數據集時的速度比AOF的恢復速度要快。

2>根據同步策略的不同,AOF在運行效率上往往會慢於RDB。總之,每秒同步策略的效率是比較高的,同步禁用策略的效率和RDB一樣高

 

 

 

Redis最適合的場景

1>會話緩存 session cache

 

2>全頁緩存(FPC)

 

3>隊列

 

4>排行榜/計數器(zset/set),獲取排行前10的用戶

 

ZRANGE user_scores 0 10 WITHSCORES

 

5>發佈、訂閱

 

Redis常見的性能問題

1>master最好不要做任何持久化工作,如RDB內存快照和AOF日誌文件。

 

假如redis裏面有1億個key,其中有10w個key是以某個固定的一致的前綴開頭的,如何將他們全部找出來?

使用keys指令可以掃除指定模式的key列表,如果是線上redis,因爲redis是單線程的。keys指令會導致線程組賽一段時間,線上服務會停頓,直到指令執行完畢,服務才能恢復,這個時候可以使用scan指令,scan指令可以無阻塞的提取出指定模式的key列表,但是會有一定的重複概率,在客戶端做一次驅蟲就可以了,但是整體所花費的時間會比直接使用keys指令長。

 

Redis過期鍵的刪除策略

Redis有三種不同的刪除策略

1>立即刪除,在設置鍵的過期時間時,創建一個回調事件,當過期時間達到時,有時間處理器自動執行鍵的刪除操作

2>惰性刪除,鍵過期了就過期了,不管。從此從dict字典中按key取值時,先檢查此key是否已經過期,如果過期了就刪除它,並返回nil,如果沒過期,就返回鍵值。

3>定時刪除,每間隔一段時間,對expires字典進行檢查,刪除裏面的過期鍵。

 

可以看到,第二種爲被動刪除,第一種和第三種爲主動刪除,且第一種實時性更高。

 

立即刪除

立即刪除能保證內存中數據的最大新鮮度。因爲他保證過期鍵值會在過期後馬上被刪除,其所佔用的內存也會隨之釋放,但是立即刪除對cpu是嘴不友好的。因爲刪除操作會佔用cpu的時間,如果剛好碰上了cpu很忙的時候,比如正在做交集或者排序等計算的時候,就會給cpu造成額外的壓力

 

而且目前redis時間處理器隨時間的處理方式-無序鏈表,超找一個key的時間複雜度爲O(n),所以並不適合用來處理大量的時間事件

 

 

惰性刪除

惰性刪除是指,某個鍵值過期後,此鍵值不會馬上被刪除,而是等到下次被使用時候,纔會被檢查到過期,此時才能得到刪除,所以惰性刪除的缺點很明顯:浪費內存。dict字典和expires字段都需要保存這個鍵值信息

 

定時刪除

從上面分析來看,立即刪除會短時間內佔用大量cpu,惰性刪除會在一段時間內浪費內存,所以定是刪除時一個折中的辦法。

定是刪除時:每個一段時間執行一次刪除操作,並通過限制刪除操作執行的時長和頻率,來減少操作刪除對cpou的影響。另一方面定是刪除也有效的減少了因惰性刪除到來的內存浪費

 

Redis使用的策略

Redis使用的過期鍵值策略是:惰性刪除加上定時刪除,兩者配合使用

 

Redis設置過期時間

expire 秒

pexpire 毫秒

expireat 將過期時間設爲timestamp所指定的秒數時間戳

pexpireat 將過期時間設爲timestamp所指定的毫秒數時間戳

 

保存過期時間

在數據庫結構中redisDb中的expires字典中保存了數據庫中所有鍵的過期時間,我們稱expires這個字典爲過期字典

 

Dict字典中保存着數據庫所有的鍵值對

 

Redis分佈式鎖

setnx 只有鍵key不存在的情況下,將鍵key的值設爲value。若鍵key已經存在,則setnx命令不做任何操作

首先,鎖要要加上過期時間,避免生成鎖卻未刪除的情況

其次,請求在更新緩存的時間可能很長,超過鎖的過期時間,此時,鎖值是隨機值,可以避免刪除其他請求創建的鎖。

//php單機鎖

$ok = $redis->set($key,$random,array(‘nx’,’ex’=>$ttl));



if($ok){

$cache->update();

if($redis->get($key) == $random){

$redis->del($key);

}

}

Redis常見性能問題和解決方案

1>master最好不要做任何持久化工作,如RDB內存快照和AOF日誌文件

2>如果數據比較重要,某個slave開啓AOF備份數據,策略設置爲每秒同步一次

3>爲了主從複製的速度和連接的穩定性,master和slave最好在一個局域網內

4>儘量避免在壓力很大的主庫上增加從庫

5>主從複製不要用圖狀結構,用單向鏈表結構更加穩定,即master<-slave1<-slave2<-slave3…

這樣的結構域方便解決單點故障,實現slave對master的替換。如果master掛了,可以立即啓用slave1作爲master,其他不變

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章