Redis哨兵、持久化、主從(轉載)

前言

  如下內容爲轉載,原文出自微信公衆號:JavaFamilynode


 

問:騷年,都說Redis很快,那你知道這是爲何嗎?

  答:英俊瀟灑的面試官,您好。咱們能夠先看一下 關係型數據庫 和 Redis 本質上的區別。面試

 

 

   Redis採用的是基於內存的,採用的是單進程單線程模型的 KV 數據庫,有C語言編寫,官方提供的數據是能夠達到 10w+ 的QPS(每秒內查詢次數)redis

  • 徹底基於內存,絕大部分請求是純粹的內存操做,很是快速。它的數據存在內存中,相似於HashMap,HashMap 的優點就是查找和操做時間的複雜度都是0(1);
  • 數據結構簡單,對數據操做也簡單,Redis 中的數據結構是專門進行設計的;
  • 採用單線程,避免了沒必要要的上下文切換和競爭條件,也不存在多進程或者多線程致使的切換而消耗 CPU ,不用去考慮各類鎖的問題,不存在加鎖、釋放鎖的操做,沒有由於可能出現死鎖而致使的性能消耗;
  • 使用多路 I/O/ 複用模型,非阻塞 IO;
  • 使用底層模型不一樣,它們之間底層實現方式以及與客戶端之間通訊的應用協議不同,Redis 直接本身構建了 VM 機制,由於通常的系統調用系統函數的話,會浪費必定的時間去移動和請求;

 

問:對上下文切換了解嗎?

  我打個比方吧:之前有人這麼問過我,上下文切換是啥,爲何會縣城不安全?我是這麼說的,就比如你看一本英文書,看到第十頁發現有個單詞不會讀,你加了個書籤,而後去查字典,過了一下子你又回來繼續從書籤那裏讀,OK,到目前爲止沒什麼問題的。數據庫

  若是是你一我的讀確定沒什麼問題的,可是你去查的時候,別人好奇你在看啥,他過來翻一下你的數,而後就跑路了。當你再回來的時候,你會發現書不是你看的那一頁了。不知道到這裏爲止,我有沒有解釋清楚,以及爲何會線程不安全,就是由於你一我的怎麼看都沒事,可是人多了,換來換去的操做,一本書的數據就亂了。可能我解釋得比較粗糙,可是道理應該是差很少的。緩存

 


 

問: 既然它是單線程的,咱們如今服務器都是多核的,那不是浪費?

  答:是的,它是單線程的,可是,咱們能夠經過在單機開多個Redis實例嘛。安全


 

問:既然提到了單機會有瓶頸,那大家是怎麼解決這個瓶頸的?

  答:咱們用到了集羣的部署方式,也就是 Redis cluster ,而且是主從同步讀寫分離,相似 MySQL 的主從同步,Redis cluster 支撐 N 個 Redis master node,每一個 master node 均可以掛載多個 slave node服務器

  這樣整個 Redis 就能夠橫向擴容了。若是你要支撐更大數據量的緩存,那就橫向擴容更多的 master 節點,每一個 master 節點就能存放更多的 數據了。微信


 

 問:那麼問題來了,他們之間是怎麼進行數據交互的?以及Redis是怎麼進行持久化的?Redis數據都在內存中,一斷電或者重啓不就木有了嘛?

  答:是的,持久化的話是 Redis 高可用中比較重要的一個環節,由於 Redis 數據再內存的特性,持久化必須得有,我瞭解到的持久化是兩種方式的。網絡

  • RDB:RDB 持久化機制,是對 Redis 中的數據執行週期性的持久化。
  • AOF:AOF 機制對每條寫入命令做爲日誌,以 append-only 的模式寫入一個日誌文件中,由於這個模式是隻追加的方式,因此沒有任何磁盤尋址的開銷,因此很快,有點像MySQL中的 binlog

  兩種方式均可以把 Redis 內存中的數據持久化到磁盤上,而後再講這些數據備份到別的地方去,RDB更適合作冷備AOF更適合作熱備,好比深圳某電商公司,有這兩個數據,我備份一份到深圳的節點,再備份一份到廣州的節點,就算髮生沒法避免的天然災害,也不會兩個地方都一塊兒掛吧,這災備也就是異地容災,要是地球毀滅當我啥也沒說。。。數據結構

  Tip:兩種機制所有開啓的時候,Redis在重啓的時候會默認使用AOF去從新構建數據,由於AOF的數據是比RDB更完整。


 

問:那這兩種機制各有什麼優缺點?

我先說RDB吧。

優勢:

  它會生成多個數據文件,每一個數據文件分別表明了某一時刻 Redis 裏面的數據,這種方式,有沒有以爲很適合作冷備,完整的數據運維設置定時任務,定時同步到雲端的服務器,好比阿里雲服務,這樣一旦線上掛了,你想恢復多少分鐘以前的數據,就去雲端拷貝一份以前的數據就行了。

  RDB對 Redis 的性能影響很是小,是由於在同步數據的時候他只是 fork 了一個子進程去作持久化,並且他在數據恢復的時候速度比AOF來的快。

缺點:

  RDB都是快照文件,都是默認五分鐘甚至更久的時間纔會生成一次,這意味着你此次同步到下次同步這中間五分鐘的數據頗有可能所有丟失。AOF則最多丟失一秒的數據,數據完整性上高低立判。

  還有就是RDB在生成數據快照的時候,若是文件很大,客戶端可能會暫停幾毫秒甚至幾秒,你公司在作秒殺或者搶單的時候,它恰好在這個時候 fork 了一個子進程去生成一個大快照,這確定要出大問題的。

咱們再來講說AOF

優勢:

  上面提到了,RDB五分鐘一次生成快照,可是AOF是一秒一次去經過一個後臺的縣城 fsync 操做,那最多丟失這一秒的數據。

  AOF在對日誌文件進行操做的時候,是以 append-only 的方式去寫的,他只是追加的方式寫數據,天然就少了不少磁盤尋址的開銷,寫入性能驚人,文件也不容易破損。

  AOF的日誌是經過一個叫很是可讀的方式記錄的,這樣的特性就適合作災難性數據誤刪除的緊急恢復了,好比某公司的實習生經過 flushall 清空了全部的數據,只要這個時候後臺重寫還沒發生,你立刻拷貝一份AOF日誌文件,把最後一條 flushall 命令刪除了就完事了。

  Tip:這命令別去線上系統操做啊!!!想試去本身買的服務器上裝個Redis試!!!

缺點

  同樣的數據,AOF文件比RDB還要大。

  AOF開啓後,Redis 支撐寫的QPS會比RDB支持寫的要低,他不是每秒都要去異步刷新一第二天志 fsync 嘛,固然即便這樣性能仍是很高,我記得 ElasticSearch 也是這樣的,異步刷新緩存區的數據去持久化,爲何這麼作,而不是來一條懟一條呢?那我會告訴你這樣性能可能低到沒辦法用的。至於爲什麼這麼作,後面記得再補了。

 


問:那二者怎麼選擇?

   答:小朋友纔會作選擇題,我全都要!你單獨使用RDB,你會丟失不少數據;你單獨使用AOF,你數據恢復沒RDB來得快,真出了什麼問題,第一時間用RDB恢復,而後AOF作數據補全,簡直不要太完美!冷備、熱備一塊兒上,纔是互聯網時代一個健壯系統的王道。


 

問:騷年,能夠呀。剛纔聽你提到了高可用,Redis還有其餘保證集羣高可用的方式嗎?

  完了,給本身挖坑了。。。(其實早有準備,就等你來問!也提醒一下,不會的知識點,回答中別說,不然真就是本身挖坑還本身往裏跳)

  答:能夠僞裝思考(略做思考,省得覺得你真的不會),哦,想起來了,還有哨兵集羣 sentinel 

  哨兵必須用三個實例去保證本身的健壯性,哨兵 + 主從 並不能保證數據不丟失,可是能夠保證集羣的高可用

  爲何必需要三個實例呢?咱們先看看兩個哨兵會咋樣。

 

  master宕機了,S1 和 S2 兩個哨兵只要有一個認爲你宕機了就切換了,而且會選舉一個哨兵去執行故障,可是這個時候也須要大多數哨兵都是運行的。

  那這樣有啥問題呢?M1宕機了,S1沒有掛,這是OK的,可是整個機器都掛了呢?哨兵就剩下S2個光桿司令了,沒有哨兵去容許故障轉移了,雖然另一個機器上還有R1,可是故障轉移就是不執行。

  經典的哨兵集羣是這樣的

   M1所在的機器掛了,哨兵還有兩個,兩我的一看M1掛了,那咱們就選舉一個出來執行故障轉移不就好了嘛。

  簡單總結下哨兵組件的主要功能

    • 集羣監控:負責監控 Redis master 和 slave 進程是否正常工做;

    • 消息通知:若是某個 Redis 實例有故障,那麼哨兵負責人發送消息做爲報警通知管理員;

    • 故障轉移:若是 master node 掛掉了,會自動轉移到 slave node 上;

    • 配置中心:若是發生了故障轉移,則通知 client 客戶端新的 master 地址。

 


問:我記得你還提到主從同步,能說一下主從之間的數據怎麼同步的嗎?

   答:提到這個,就跟我前面提到的數據持久化的 RDB 和 AOF 有着密切的關係了。

  我先說說爲何要用主從這樣的架構模式,前面提到了單機 QPS 是有上限的,並且Redis的特性就是必須支撐讀高併發的,那你一臺機器又讀又寫,就算是機器也扛不住啊。可是你讓這個 master 機器去寫,數據同步給別的 slave 機器,他們都拿去讀,分發掉大量的請求那就會好不少,並且擴容的時候還能夠輕鬆實現水平擴容。

 

 

 

 

  迴歸正題,他們的數據是怎麼同步的呢?

   你啓動了一臺 slave 的時候,他會發送一個 psync 命令給 master,若是是這個 slave 第一次鏈接到 master,他會觸發一個全量複製。master 就會啓動一個線程,生成 RDB快照,還會把新的寫請求都緩存在內存中,RDB文件生成後,master 會將這個 RDB 發送給 slave 的,slave 拿到以後作的第一件事情就是寫進本地的磁盤,而後加載進內存,而後 master 會把內存裏面的緩存的那些新命名都發給 slave。

 


 

問:數據傳輸的時候斷網了或者服務器掛了怎麼辦呀?

  答:傳輸過程當中有什麼網絡問題的,會自動重連的,而且鏈接以後會把缺乏的數據不上。

  Tip:你們須要記住的是,RDB快照的數據生成的時候,緩存區也必須同時開始接受新請求,否則你舊的數據過去了,你在同步期間的增量數據咋辦?對吧?

 


 

問:說了這麼多,你能說一下他的內存淘汰機制嗎?

  答:Redis 的過時策略,是有按期刪除惰性刪除兩種。

  按期刪除好理解,就是默認100s就隨機抽取一些設置了過時時間的key,去檢查是否過時,過時了就刪除。


 

問:爲何不掃描所有設置了過時時間的key呢?

  答:假如Redis裏面全部的key都有過時時間,再全掃描一遍?這太恐怖了,並且咱們線上基本上都會設置必定的過時時間。全掃描就跟你去查數據庫不帶where條件、不走索引全表掃描同樣,100s一次,會給 CPU 帶來很大的負載!


問:若是一直沒有隨機到不少key,裏面不就存在大量的無效key了?

  答:這就回到剛纔說的惰性刪除了。見名知意,惰性嘛,就是我不主動刪,我懶,我等你來查詢了,再看看你過時了沒,過時就刪除還不給你返回,沒過時該怎樣就怎樣。


 

問:爲何要採用按期刪除+惰性刪除這2種策略呢?

  答:若是過時就刪除,假設Redis裏放了10萬個key,都設置了過時時間,你每隔幾把毫秒,就檢查10萬個key,那Redis基本上就死了,CPU負載會很高的,基本都消耗在你的檢查過時key上。

  可是問題是,按期刪除可能回致使不少過時key到了時間並無被刪除掉,那應該怎麼處理呢?因此就有了惰性刪除了。這就是說,在你獲取某個key的時候,redis會檢查一下,這個key若是設置了過時時間,那麼是否過時了?若是過時了此時就會刪除,不會給你返回任何東西。

  並非key到了時間就被刪除,而是你查詢這個key的時候,redis再懶惰地檢查一下。

  經過上述兩種手段結合起來,保證過時的key必定會被刪除。

  因此說,用了上述2種策略後,這種現象就不難解釋了:數據明明都過時了,可是還佔着內存


 

問:最後的若是按期沒刪,我也沒查詢,會出現什麼狀況,那怎麼辦呢?

  答:會出現大量的key堆積在內存裏,致使redis內存很快耗盡。使用redis內存淘汰機制解決這個問題。

  可能有的小夥伴遇到過這種狀況,放在redis中的數據怎麼沒了?

  由於Redis將數據放到內存中,內存時有限的,好比redis就只能用10個G,你要是忘裏面寫了20G的數據,會出現什麼狀況?固然是會幹掉10個G的數據,而後保留10個G的數據了。那幹掉哪些數據?保留哪些數據?固然時幹掉不經常使用的數據,保留經常使用的數據了。

  Redis提供了6中數據淘汰策略:

  1. no-eviction:不會繼續服務寫請求(DEL請求能夠繼續服務),讀請求能夠繼續進行。這樣能夠保證不會丟失數據,可是會讓線上的業務不能持續進行。這是默認的淘汰策略。

  2. volatile-lru:嘗試淘汰設置了過時時間的key,最少使用的key優先淘汰。沒有設置過時時間的key
    不會淘汰,這樣能夠保證須要持久化的數據不會忽然丟失。(這個是使用最多的)

  3. volatile-ttl:跟上面同樣,除了淘汰的策略不是LUR,而是key的剩餘壽命 ttl 的值,ttl 越小越優先淘汰,即淘汰即將要過時的數據。

  4. volatile-random:從已設置過時時間的數據集中隨機選取數據淘汰。

  5. allkeys-lru:區別於 volatile-lru,這個策略要淘汰的key對象是全體的key集合,而不僅是過時的key集合。這意味着沒有設置過時時間的key也會被淘汰。

  6. allkeys-random:從全體的key集合中任意選擇數據淘汰。
相關文章
相關標籤/搜索