1. 程式人生 > 其它 >Redis學習記錄-001

Redis學習記錄-001

Redis是什麼?

Redis是C語言開發的一個開源的(遵從BSD協議)高效能鍵值對(key-value)的記憶體資料庫,可以用作資料庫、快取、訊息中介軟體等。它是一種NoSQL(not-only sql,泛指非關係型資料庫)的資料庫。
Redis作為一個記憶體資料庫。
1、效能優秀,資料在記憶體中,讀寫速度非常快,支援併發10W QPS;
2、單程序單執行緒,是執行緒安全的,採用IO多路複用機制;
3、豐富的資料型別,支援字串(strings)、雜湊(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等;
4、支援資料持久化。可以將記憶體中資料儲存在磁碟中,重啟時載入;
5
、主從複製,哨兵,高可用;
6、可以用作分散式鎖;
7、可以作為訊息中介軟體使用,支援釋出訂閱

Redis的快取雪崩

目前電商首頁以及熱點資料都會去做快取,一般快取都是定時任務去重新整理,或者查不到之後去更新快取的,定時任務重新整理就有一個問題。舉個栗子:如果首頁所有Key的失效時間都是12小時,中午12點重新整理的,我零點有個大促活動大量使用者湧入,假設每秒6000個請求,
本來快取可以抗住每秒5000個請求,但是快取中所有Key都失效了。此時6000個/秒的請求全部落在了資料庫上,資料庫必然扛不住,真實情況可能DBA都沒反應過來直接掛了,此時,如果沒什麼特別的方案來處理,DBA很著急,重啟資料庫,但是資料庫立馬又被新流量給打死了。
這就是我理解的快取雪崩。

快取雪崩的解決方案

處理快取雪崩簡單,在批量往Redis存資料的時候,把每個Key的失效時間都加個隨機值就好了,這樣可以保證資料不會再同一時間大面積失效。
setRedis(key, value, time+Math.random()*10000);
如果Redis是叢集部署,將熱點資料均勻分佈在不同的Redis庫中也能避免全部失效。或者設定熱點資料永不過期,有更新操作就更新快取就好了(比如運維更新了首頁商品,那你刷下快取就好了,不要設定過期時間),電商首頁的資料也可以用這個操作,保險。

快取穿透和擊穿,跟雪崩的區別

快取穿透是指快取和資料庫中都沒有的資料,而使用者(黑客)不斷髮起請求,舉個栗子:我們資料庫的id都是從1自增的,如果發起id=-1的資料或者id特別大不存在的資料,這樣的不斷攻擊導致資料庫壓力很大,嚴重會擊垮資料庫。
快取擊穿嘛,這個跟快取雪崩有點像,但是又有一點不一樣,快取雪崩是因為大面積的快取失效,打崩了DB,而快取擊穿不同的是快取擊穿是指一個Key非常熱點,在不停地扛著大量的請求,大併發集中對這一個點進行訪問,
當這個Key在失效的瞬間,持續的大併發直接落到了資料庫上,就在這個Key的點上擊穿了快取。

快取穿透和擊穿解決方案

快取穿透我會在介面層增加校驗,比如使用者鑑權,引數做校驗,不合法的校驗直接return,比如id做基礎校驗,id<=0直接攔截。
Redis裡還有一個高階用法布隆過濾器(Bloom Filter) 這個也能很好的預防快取穿透的發生,他的原理也很簡單,就是利用高效的資料結構和演算法快速判斷出你這個Key是否在資料庫中存在,不存在你return就好了,存在你就去查DB重新整理KV再return。
快取擊穿的話,設定熱點資料永不過期,或者加上互斥鎖就搞定了。

六種淘汰策略

補充一下:Redis4.0加入了LFU(least frequency use)淘汰策略,包括volatile-lfu和allkeys-lfu,通過統計訪問頻率,將訪問頻率最少,即最不經常使用的KV淘汰。

Redis是單執行緒還是多執行緒呢?

Redis在4.0之前使用的是單執行緒模式,之後增加了對多執行緒的支援。
4.0之前的單執行緒模式,也只是說他的網路IO執行緒以及Set和Get操作是一個執行緒完成的,持久化、叢集同步還是在其他執行緒來完成的。
4.0之後添加了對多執行緒的支援,主要體現在大資料的非同步刪除功能,例如:unlink key、fulshdb async、fulshall async等

那為什麼Redis在4.0之前會選擇使用單執行緒?而且使用單執行緒還那麼快?

Redis的操作都是在記憶體中,記憶體中進行操作本來就很快,不存在鎖競爭,在無鎖的情況下完成所有操作,自然也不會存在死鎖以及執行緒切換帶來的效能和時間上的開銷。
快的原因:
1、大部分操作在記憶體中操作
2、單執行緒避免了多執行緒的切換開銷
3、採用I/O多路複用機制處理大量客戶端的socket請求,基於非阻塞的I/O模型,是Redis可以搞笑的進行網路通訊

那Redis是如何實現資料不丟失的呢?

三種方式
AOF(append only file)將redis操作成功後的命令以追加的方式寫入檔案中並儲存到硬碟進行實現資料持久化,也就是寫後記錄,因為redis不對執行命令進行語法校驗,所有隻記錄成功執行的操作。
RDB(Redis DataBase)將某一個時刻的記憶體資料通過二進位制的方式寫入磁碟從而實現資料持久化。
AOF和RDB的混合使用

AOF和 RDB的實現原理

AOF:將成功執行的Redis操作命令寫入到檔案中,然後寫入磁碟中,儲存的主要是操作命令,如果資料丟失,需要將操作命令全部執行即可。AOF可以做到全程持久化,只需要在配置中開啟 appendonly yes。這樣redis每執行一個修改資料的命令,
都會把它新增到AOF檔案中,當redis重啟時,將會讀取AOF檔案進行重放,恢復到redis關閉前的最後時刻。
優點:會讓redis變得非常耐久。可以設定不同的fsync策略,aof的預設策略是每秒鐘fsync一次,在這種配置下,就算髮生故障停機,也最多丟失一秒鐘的資料。
缺點:對於相同的資料集來說,AOF的檔案體積通常要大於RDB檔案的體積。根據所使用的fsync策略,AOF的速度可能會慢於RDB。
RDB:將記憶體中的資料全量進行備份,記錄某一個時刻的所有資料,所以資料丟失時,直接將RDB資料讀取到記憶體中即可。預設Redis是會以快照"RDB"的形式將資料持久化到磁碟的一個二進位制檔案dump.rdb。當Redis需要做持久化時,Redis會fork一個子程序,
子程序將資料寫到磁碟上一個臨時RDB檔案中。當子程序完成寫臨時檔案後,將原來的RDB替換掉,這樣的好處是可以copy-on-write
優點:這種檔案非常適合用於備份:比如,你可以在最近的24小時內,每小時備份一次,並且在每個月的每一天也備份一個RDB檔案。這樣的話,即使遇上問題,也可以隨時將資料集還原到不同的版本。RDB非常適合災難恢復。
缺點:如果你需要儘量避免在伺服器故障時丟失資料,那麼RDB不合適你

如何選擇AOF和RDB

如果你非常關心你的資料,但仍然可以承受數分鐘內的資料丟失,那麼可以只使用RDB持久。
AOF將Redis執行的每一條命令追加到磁碟中,處理巨大的寫入會降低Redis的效能,不知道你是否可以接受。
資料庫備份和災難恢復:定時生成RDB快照非常便於進行資料庫備份,並且RDB恢復資料集的速度也要比AOF恢復的速度快。
當然了,redis支援同時開啟RDB和AOF,系統重啟後,redis會優先使用AOF來恢復資料,這樣丟失的資料會最少

Redis為什麼要先執行命令,再把資料寫入日誌呢

Redis執行命令是沒有進行語法校驗,為了避免記錄錯誤命令,所以使用寫後記錄

後寫日誌又有什麼風險呢

在執行命令後,還沒來得及記錄時發生故障,則會造成資料丟失。

RDB做快照時會阻塞執行緒嗎

RDB做快照有兩種方式,一種是通過save進行操作,是直接在主執行緒中操作。這樣做快照時會造成阻塞。另外一種是bgsave,是另外建立一個子執行緒進行操作,不會造成阻塞。預設使用bgsave.

RDB 做快照的時候資料能修改嗎

save是同步的所以會造成阻塞導致不能同步修改資料,bgsave可以修改。

Redis是怎麼解決在bgsave做快照的時候允許資料修改呢

在進行讀操作時,互不影響,在寫操作時,會將修改的資料生成一個副本,然後將副本中的資料儲存到RDB的檔案中

Redis如何實現高可用

主從模式:一主多從
哨兵模式:一主多從模式基礎上新增一臺監控,當主節點發生故障後,直接進行容災恢復
叢集模式:多臺機器部署一主多從

使用哨兵模式在資料上有副本資料做保證,在可用性上又有哨兵監控,一旦master宕機會選舉salve節點為master節點,這種已經滿足了我們的生產環境需要,那為什麼還需要使用叢集模式呢?

主要為了擴充套件寫能力和儲存能力

參考連結:https://mp.weixin.qq.com/s/7f43n89J9VvqngZKIt16AA https://mp.weixin.qq.com/s/QBkYNnKHIBl55ZJ8VAcc2g