redis是鍵值對的數據庫,經常使用的五種數據類型爲字符串類型(string),散列類型(hash),列表類型(list),集合類型(set),有序集合類型(zset)redis
Redis用做緩存,主要兩個用途:高性能,高併發,由於內存自然支持高併發數據庫
分佈式鎖(string)瀏覽器
setnx key value,當key不存在時,將 key 的值設爲 value ,返回1。若給定的 key 已經存在,則setnx不作任何動做,返回0。緩存
當setnx返回1時,表示獲取鎖,作完操做之後del key,表示釋放鎖,若是setnx返回0表示獲取鎖失敗,總體思路大概就是這樣,細節仍是比較多的,有時間單開一篇來說解服務器
計數器(string)併發
如知乎每一個問題的被瀏覽器次數dom
消息隊列(list)分佈式
在list裏面一邊進,一邊出便可高併發
新浪/Twitter用戶消息列表(list)性能
假如說小編li關注了2個微博a和b,a發了一條微博(編號爲100)就執行以下命令
b發了一條微博(編號爲200)就執行以下命令:
假如想拿最近的10條消息就能夠執行以下命令(最新的消息必定在list的最左邊):
抽獎活動(set)
實現點贊,簽到,like等功能(set)
實現關注模型,可能認識的人(set)
seven關注的人
sevenSub -> {qing, mic, james}
青山關注的人
qingSub->{seven,jack,mic,james}
Mic關注的人
MicSub->{seven,james,qing,jack,tom}
電商商品篩選(set)
每一個商品入庫的時候即會創建他的靜態標籤列表如,品牌,尺寸,處理器,內存
排行版(zset)
redis的zset天生是用來作排行榜的、好友列表, 去重, 歷史記錄等業務需求
按期刪除
redis 會將每一個設置了過時時間的 key 放入到一個獨立的字典中,之後會按期遍歷這個字典來刪除到期的 key。
按期刪除策略
Redis 默認會每秒進行十次過時掃描(100ms一次),過時掃描不會遍歷過時字典中全部的 key,而是採用了一種簡單的貪心策略。
從過時字典中隨機 20 個 key;
刪除這 20 個 key 中已通過期的 key;
若是過時的 key 比率超過 1/4,那就重複步驟 1;
惰性刪除
除了按期遍歷以外,它還會使用惰性策略來刪除過時的 key,所謂惰性策略就是在客戶端訪問這個 key 的時候,redis 對 key 的過時時間進行檢查,若是過時了就當即刪除,不會給你返回任何東西。
按期刪除是集中處理,惰性刪除是零散處理。
爲何要採用按期刪除+惰性刪除2種策略呢?
若是過時就刪除。假設redis裏放了10萬個key,都設置了過時時間,你每隔幾百毫秒,就檢查10萬個key,那redis基本上就死了,cpu負載會很高的,消耗在你的檢查過時key上了
可是問題是,按期刪除可能會致使不少過時key到了時間並無被刪除掉,那咋整呢?因此就是惰性刪除了。這就是說,在你獲取某個key的時候,redis會檢查一下 ,這個key若是設置了過時時間那麼是否過時了?若是過時了此時就會刪除,不會給你返回任何東西。
並非key到時間就被刪除掉,而是你查詢這個key的時候,redis再懶惰的檢查一下
經過上述兩種手段結合起來,保證過時的key必定會被幹掉。
因此說用了上述2種策略後,下面這種現象就不難解釋了:數據明明都過時了,可是還佔有着內存
這個問題可能有小夥伴們遇到過,放到Redis中的數據怎麼沒了?
由於Redis將數據放到內存中,內存是有限的,好比redis就只能用10個G,你要是往裏面寫了20個G的數據,會咋辦?固然會幹掉10個G的數據,而後就保留10個G的數據了。那幹掉哪些數據?保留哪些數據?固然是幹掉不經常使用的數據,保留經常使用的數據了
Redis提供的內存淘汰策略有以下幾種:
1.noeviction 不會繼續服務寫請求 (DEL 請求能夠繼續服務),讀請求能夠繼續進行。這樣能夠保證不會丟失數據,可是會讓線上的業務不能持續進行。這是默認的淘汰策略。
2.volatile-lru 嘗試淘汰設置了過時時間的 key,最少使用的 key 優先被淘汰。沒有設置過時時間的 key 不會被淘汰,這樣能夠保證須要持久化的數據不會忽然丟失。(這個是使用最多的)
3.volatile-ttl 跟上面同樣,除了淘汰的策略不是 LRU,而是 key 的剩餘壽命 ttl 的值,ttl 越小越優先被淘汰。
4.volatile-random 跟上面同樣,不過淘汰的 key 是過時 key 集合中隨機的 key。
5.allkeys-lru 區別於 volatile-lru,這個策略要淘汰的 key 對象是全體的 key 集合,而不僅是過時的 key 集合。這意味着沒有設置過時時間的 key 也會被淘汰。
6.allkeys-random 跟上面同樣,不過淘汰的策略是隨機的 key。allkeys-random 跟上面同樣,不過淘汰的策略是隨機的 key。
Redis的數據是存在內存中的,若是Redis發生宕機,那麼數據會所有丟失,所以必須提供持久化機制。
Redis 的持久化機制有兩種,第一種是快照(RDB),第二種是 AOF 日誌。快照是一次全量備份,AOF 日誌是連續的增量備份。快照是內存數據的二進制序列化形式,在存儲上很是緊湊,而 AOF 日誌記錄的是內存數據修改的指令記錄文本。AOF 日誌在長期的運行過程當中會變的無比龐大,數據庫重啓時須要加載 AOF 日誌進行指令重放,這個時間就會無比漫長。因此須要按期進行 AOF 重寫,給 AOF 日誌進行瘦身。
RDB是經過Redis主進程fork子進程,讓子進程執行磁盤 IO 操做來進行 RDB 持久化,AOF 日誌存儲的是 Redis 服務器的順序指令序列,AOF 日誌只記錄對內存進行修改的指令記錄。即RDB記錄的是數據,AOF記錄的是指令
RDB和AOF到底該如何選擇?
1.不要僅僅使用 RDB,由於那樣會致使你丟失不少數據,由於RDB是隔一段時間來備份數據
2.也不要僅僅使用 AOF,由於那樣有兩個問題,第一,經過 AOF 作冷備沒有RDB恢復速度快; 第二,RDB 每次簡單粗暴生成數據快照,更加健壯,能夠避免 AOF 這種複雜的備份和恢復機制的 bug
3.用RDB恢復內存狀態會丟失不少數據,重放AOP日誌又很慢。Redis4.0推出了混合持久化來解決這個問題。將 rdb 文件的內容和增量的 AOF 日誌文件存在一塊兒。這裏的 AOF 日誌再也不是全量的日誌,而是自持久化開始到持久化結束的這段時間發生的增量 AOF 日誌,一般這部分 AOF 日誌很小。因而在 Redis 重啓的時候,能夠先加載 rdb 的內容,而後再重放增量 AOF 日誌就能夠徹底替代以前的 AOF 全量文件重放,重啓效率所以大幅獲得提高。
緩存雪崩是什麼?
假設有以下一個系統,高峯期請求爲5000次/秒,4000次走了緩存,只有1000次落到了數據庫上,數據庫每秒1000的併發是一個正常的指標,徹底能夠正常工做,但若是緩存宕機了,每秒5000次的請求會所有落到數據庫上,數據庫立馬就死掉了,由於數據庫一秒最多抗2000個請求,若是DBA重啓數據庫,立馬又會被新的請求打死了,這就是緩存雪崩。
如何解決緩存雪崩
事前:redis高可用,主從+哨兵,redis cluster,避免全盤崩潰
事中:本地ehcache緩存 + hystrix限流&降級,避免MySQL被打死
過後:redis持久化,快速恢復緩存數據
緩存穿透是什麼?
假如客戶端每秒發送5000個請求,其中4000個爲黑客的惡意攻擊,即在數據庫中也查不到。舉個例子,用戶id爲正數,黑客構造的用戶id爲負數,
若是黑客每秒一直髮送這4000個請求,緩存就不起做用,數據庫也很快被打死。
如何解決緩存穿透
查詢不到的數據也放到緩存,value爲空,如set -999 「」
總而言之,緩存雪崩就是緩存失效,請求所有所有打到數據庫,數據庫瞬間被打死。緩存穿透就是查詢了一個必定不存在的數據,而且從存儲層查不到的數據沒有寫入緩存,這將致使這個不存在的數據每次請求都要到存儲層去查詢,失去了緩存的意義