2020互聯網公司面試 Redis必問技術點

Redis

介紹

key-value nosql非關係型數據庫 單線程,c語言開發,效率高(完全基於內存,非阻塞IO,大部分命令時間複雜度都是O(1)所以速度快)。因爲是單線程,時間複雜度爲 O(N) 的 KEYS 命令,嚴格禁止在生產環境中使用!

Key

1. 不要使用過長的Key。例如使用一個1024字節的key就不是一個好主意,不僅會消耗更多的內存,還會導致查找的效率降低
2. Key短到缺失了可讀性也是不好的,例如u1000flw比起user:1000:followers來說,節省了寥寥的存儲空間,卻引發了可讀性和可維護性上的麻煩
3. 最好使用統一的規範來設計Key,比如object-type:id:attr,以這一規範設計出的Key可能是user:1000或comment:1234:reply-to
4. Redis允許的最大Key長度是512MB(對Value的長度限制也是512MB)

基本數據類型常用五種

1. String 是Redis的基礎數據類型,Redis沒有Int、Float、Boolean等數據類型的概念,所有的基本類型在Redis中都以String體現。
2. List 注意:鏈表結構,Redis的List實際是設計來用於實現隊列,而不是用於實現類似ArrayList這樣的列表的。如果你不是想要實現一個雙端出入的隊列,那麼請儘量不要使用Redis的List數據結構。
3. Hash 理解成java的hashMap,存儲對象比較實用,可以實現二元查找,如”查找ID爲1000的用戶的年齡”。比起將整個對象序列化後作爲String存儲的方法,Hash能夠有效地減少網絡傳輸的消耗
4. Set 是無序的,不可重複的String集合。
5. Sorted Set 是有序的、不可重複的String集合。Sorted Set中的每個元素都需要指派一個分數(score),Sorted Set會根據score對元素進行升序排序。如果多個member擁有相同的score,則以字典序進行升序排序。Sorted Set非常適合用於實現排名。

數據持久化

生產開啓兩種措施,RDB默認開啓,AOP 配置文件:appendonly yes 開啓

RDB(執行時間間隔生成rdb快照)

採用RDB持久方式,Redis會定期保存數據快照至一個rbd文件中,並在啓動時自動加載rdb文件,恢復之前保存的數據。可以在配置文件中配置Redis進行快照保存的時機:

save [seconds] [changes]

意爲在[seconds]秒內如果發生了[changes]次數據修改,則進行一次RDB快照保存

優點:

1. 對性能影響最小。如前文所述,Redis在保存RDB快照時會fork出子進程進行,幾乎不影響Redis處理客戶端請求的效率。
2. 每次快照會生成一個完整的數據快照文件,所以可以輔以其他手段保存多個時間點的快照(例如把每天0點的快照備份至其他存儲媒介中),作爲非常可靠的災難恢復手段。
3. 使用RDB文件進行數據恢復比使用AOF要快很多。

缺點:

1. 快照是定期生成的,所以在Redis crash時或多或少會丟失一部分數據。
2. 如果數據集非常大且CPU不夠強(比如單核CPU),Redis在fork子進程時可能會消耗相對較長的時間(長至1秒),影響這期間的客戶端請求。

AOF(把每一個寫請求都記錄在一個日誌文件裏)

AOF提供了三種fsync配置,always/everysec/no,通過配置項[appendfsync]指定:

1. appendfsync no:不進行fsync,將flush文件的時機交給OS決定,速度最快
2. appendfsync always:每寫入一條日誌就進行一次fsync操作,數據安全性最高,但速度最慢
3. appendfsync everysec:折中的做法,交由後臺線程每秒fsync一次

優點:

1. 最安全,在啓用appendfsync always時,任何已寫入的數據都不會丟失,使用在啓用appendfsync everysec也至多隻會丟失1秒的數據。
2. AOF文件在發生斷電等問題時也不會損壞,即使出現了某條日誌只寫入了一半的情況,也可以使用redis-check-aof工具輕鬆修復。
3. AOF文件易讀,可修改,在進行了某些錯誤的數據清除操作後,只要AOF文件沒有rewrite,就可以把AOF文件備份出來,把錯誤的命令刪除,然後恢復數據。

缺點:

1. AOF文件通常比RDB文件更大
2. 性能消耗比RDB高
3. 數據恢復速度比RDB慢

架構演變集羣高可用方案(延伸擴展問題等)

1. 普通主從模式:避免單點故障,讀寫分離,但是master掛了需要手動重啓
2. 哨兵模式高可用:監控redis集羣狀態:主要功能兩個(1)監控主數據庫和從數據庫是否正常運行。(2)主數據庫出現故障時自動將從數據庫轉換爲主數據庫。
3. redis-cluster羣集高可用:上面兩個都是全量存儲redis數據,浪費內存並且有木桶效應,此配置最低3主3從,設計成共有16384個hash slot(hash槽)。每個master分得一部分slot,其算法爲:hash_slot = crc16(key) mod 16384 ,這就找到對應slot。

內存管理與數據淘汰機制

內存管理

在32位OS中,Redis最大使用3GB的內存,在64位OS中則沒有限制。
在使用Redis時,應該對數據佔用的最大空間有一個基本準確的預估,併爲Redis設定最大使用的內存。否則在64位OS中Redis會無限制地佔用內存(當物理內存被佔滿後會使用swap空間),容易引發各種各樣的問題。
通過如下配置控制Redis使用的最大內存:

maxmemory 100mb

在內存佔用達到了maxmemory後,再向Redis寫入數據時,Redis會:

1. 根據配置的數據淘汰策略嘗試淘汰數據,釋放空間
2. 如果沒有數據可以淘汰,或者沒有配置數據淘汰策略,那麼Redis會對所有寫請求返回錯誤,但讀請求仍然可以正常執行

在爲Redis設置maxmemory時,需要注意:
如果採用了Redis的主從同步,主節點向從節點同步數據時,會佔用掉一部分內存空間,如果maxmemory過於接近主機的可用內存,導致數據同步時內存不足。所以設置的maxmemory不要過於接近主機可用的內存,留出一部分預留用作主從同步。

數據淘汰機制

Redis提供了5種數據淘汰策略:

1. volatile-lru:使用LRU算法進行數據淘汰(淘汰上次使用時間最早的,且使用次數最少的key),只淘汰設定了有效期的key
2. volatile-random:隨機淘汰數據,只淘汰設定了有效期的key
3. allkeys-lru:使用LRU算法進行數據淘汰,所有的key都可以被淘汰
4. allkeys-random:隨機淘汰數據,所有的key都可以被淘汰
5. volatile-ttl:淘汰剩餘有效期最短的key

最好爲Redis指定一種有效的數據淘汰策略以配合maxmemory設置,避免在內存使用滿後發生寫入失敗的情況。
一般來說,推薦使用的策略是volatile-lru,並辨識Redis中保存的數據的重要性。

緩存穿透,緩存雪崩,緩存擊穿

緩存穿透

緩存穿透是指查詢一個一定不存在的數據,由於緩存是不命中時需要從數據庫查詢,查不到數據則不寫入緩存,這將導致這個不存在的數據每次請求都要到數據庫去查詢,造成緩存穿透。

1. 過濾,首先對key的定義進行約束規範,對不符合的key直接返回,或者採用算法or存儲key的方案來校驗key的準確性。
2. 如果一個查詢返回的數據爲空(不管是數據不存在,還是系統故障),我們仍然把這個空結果進行緩存,但必須設置過期時間。防止後續真實創建這個key。

緩存雪崩

如果緩存key集中在一段時間內失效,並且查詢壓力大,所有的查詢都落在數據庫上,造成了緩存雪崩。

1. 緩存數據的過期時間設置隨機,防止同一時間大量數據過期現象發生。
2. 如果緩存數據庫是分佈式部署,將熱點數據均勻分佈在不同搞得緩存數據庫中。
3. 設置熱點數據永遠不過期。

緩存擊穿

緩存擊穿是指緩存中沒有但數據庫中有的數據(一般是緩存時間到期),這時由於併發用戶特別多,同時讀緩存沒讀到數據,又同時去數據庫去取數據,引起數據庫壓力瞬間增大,造成過大壓力

1. 設置熱點數據永遠不過期。
2. 加互斥鎖
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章