1 什麼是redis?redis
Redis 是一個基於內存的高性能key-value數據庫。數據庫
2. Memcache與Redis的區別都有哪些?緩存
1)存儲方式服務器
Memecache把數據所有存在內存之中,斷電後會掛掉,數據不能超過內存大小。網絡
Redis能夠把數據保存在硬盤上,用來保證數據的持久性。數據結構
2)數據類型dom
Memcache的數據類型比較簡單。異步
Redis有複雜的數據類型。分佈式
3)使用底層模型不一樣性能
它們之間底層的實現方式 以及與客戶端之間通訊的應用協議不同。
4)value大小
redis最大能夠達到1GB,而memcache只有1MB
3.Redis有哪些數據結構?
字符串String、字典Hash、列表List、集合Set、有序集合SortedSet。
更進一步,redis還有數據結構HyperLogLog、Geo、Pub/Sub、BloomFilter,RedisSearch,Redis-ML等
4.爲何redis須要把全部數據放到內存中?
Redis爲了達到最快的讀寫速度,將數據都讀到內存中,並經過異步的方式將數據寫入磁盤。因此redis具備快速和數據持久化的特徵。
若是不將數據放在內存中,磁盤I/O速度爲嚴重影響redis的性能。
若是設置了最大使用的內存,則數據量達到內存限值後,將不能繼續插入新值。
5.怎麼用Redis建立分佈式鎖
先用setnx來爭搶鎖,搶到以後,再用expire給鎖加一個過時時間防止鎖忘記了釋放。
注意:若是在setnx以後,而且在執行expire以前,進程意外崩潰或者要重啓維護了,這個鎖就永遠得不到釋放了。
爲了解決這個問題,set指令有很是複雜的參數,能夠同時把setnx和expire合成一條指令
6.假如Redis裏面有1億個key,其中有10萬個key是以固定的前綴開頭的,如何將這些所有找出來?
使用keys命令能夠掃出指定模式的key列表。
可是,若是這個redis正在給線上的業務提供服務,由於redis的單線程的,因此keys命令會致使線程阻塞一段時間,線上服務會停頓,直到命令執行完畢,服務才能恢復。
爲了解決這個問題,可使用scan命令,scan命令能夠無阻塞的提取出指定模式的key列表,會有必定的重複機率,在客戶端作一次去重就能夠了,可是總體所花費的時間會比直接用keys命令長。
7.若是有大量的key須要設置同一時間過時,須要如何處理?
若是大量的key過時時間設置的過於集中,那麼當到了過時的那個時間點,redis可能會出現短暫的卡頓。
這種狀況下,能夠在時間上加一個隨機值,使得過時時間分散一些。
8.Redis如何作持久化的?
bgsave作鏡像全量持久化,aof作增量持久化。
由於bgsave會耗費較長時間,達不到實時,在停機的時候會致使大量丟失數據,因此須要aof來配合使用。
若是不要求性能,在每條寫指令時都sync一下磁盤,就不會丟失數據。可是在高性能的要求下每次都sync是不現實的,通常都使用定時sync,好比1秒1次,這個時候最多會丟失1s的數據。
Redis會按期作aof重寫,壓縮aof文件日誌大小。
在redis實例重啓時,優先使用aof來恢復內存的狀態,若是沒有aof日誌,就會使用rdb文件來恢復。
9.講一下對Redis的同步機制的理解
Redis可使用主從同步,從從同步。
第一次同步時,主節點作一次bgsave,並同時將後續修改操做記錄到內存buffer,待完成後將rdb文件全量同步到複製節點,複製節點接受完成後將rdb鏡像加載到內存。
加載完成後,再通知主節點將期間修改的操做記錄同步到複製節點進行重放就完成了同步過程。
10 對Redis的回收策略的理解
volatile-lru:從已設置過時時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰
volatile-ttl:從已設置過時時間的數據集(server.db[i].expires)中挑選將要過時的數據淘汰
volatile-random:從已設置過時時間的數據集(server.db[i].expires)中任意選擇數據淘汰
allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰
allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰
no-enviction(驅逐):禁止驅逐數據
11 對多級緩存的理解?
多級緩存就是有多個緩存,將ehcache配合redis緩存,好比ehcache做爲1級緩存,使用redis做爲2級緩存。
12 如何解決DB和緩存一致性問題?
當修改了數據庫後,沒有及時修改緩存就會形成不一致的狀況。
而修改緩存失敗的狀況,最主要的緣由就是緩存服務器掛了。
若是由於網絡問題引發的沒有及時更新,能夠經過重試機制來解決。
然而若是緩存服務器死了,那麼客戶端的請求天然也就沒法到達,從而請求會直接打到數據庫。
所以,咱們在修改數據庫後,沒法修改緩存,那麼其中一個方案能夠將這條數據放到數據庫中,同時啓動一個異步任務,定時去檢測緩存服務器是否鏈接成功,一旦鏈接成功則從數據庫中按順序取出未同步的數據,依次進行同步緩存。
13.如何解決緩存穿透
生產中,一般都是先檢查緩存中是否存在,若是存在直接返回緩存中內容,若是不存在就直接查詢數據庫,而後再緩存查詢結果並返回。
這個時候若是查詢的某一個數據在緩存中一直不存在,就會形成每一次請求都查詢DB,這樣緩存就失去了做用,在流量大時,就形成了緩存穿透。
有一個解決方案,能夠將這個不存在的key預先設定一個值。是將緩存的KEY預先設置一個值,如,"key":"&&"。
若是查詢請求過來,獲得的返回值是發現是預先設定的"&&", 那咱們的應用就能夠決定是否繼續等待繼續訪問,仍是放棄掉此次操做。
若是繼續等待訪問,過一個時間輪詢點後,再次請求這個key,若是取到的值再也不是"&&",則認爲這時候key有值了,從而把大量的相似請求阻擋在緩存之中,也就避免了緩存穿透。
13. redis常見性能問題和解決方案
(1) Master最好不要作任何持久化工做,如RDB內存快照和AOF日誌文件
(2) 若是數據比較重要,某個Slave開啓AOF備份數據,策略設置爲每秒同步一次
(3) 爲了主從複製的速度和鏈接的穩定性,Master和Slave最好在同一個局域網內
(4) 儘可能避免在壓力很大的主庫上增長從庫
(5) 主從複製不要用圖狀結構,用單向鏈表結構更爲穩定,即:Master <- Slave1 <- Slave2 <- Slave3...
這樣的結構方便解決單點故障問題,實現Slave對Master的替換。若是Master掛了,能夠馬上啓用Slave1作Master,其餘不變。