Redis哨兵、持久化、主从
? ? ? ? ? ? ? ? ? ? ? ? ? ?Redis哨兵、持久化、主從
?1 為啥Redis那么快
2 單線程的,我們現在服務器都是多核的,那不是很浪費?
3 Redis cluster
4?他們之間是怎么進行數據交互的?以及Redis是怎么進行持久化的?Redis數據都在內存中,一斷電或者重啟不就木有了嘛?
那這兩種機制各自優缺點是啥?
5 主從之間的數據怎么同步的么?
6?數據傳輸的時候斷網了或者服務器掛了怎么辦啊?
7 為啥不掃描全部設置了過期時間的key呢?
? ? ? ? ?參考文獻
?1 為啥Redis那么快
Redis采用的是基于內存的采用的是單進程單線程模型的 KV 數據庫,由C語言編寫,官方提供的數據是可以達到100000+的QPS(每秒內查詢次數)。
?
-
完全基于內存,絕大部分請求是純粹的內存操作,非常快速。它的數據存在內存中,類似于HashMap,HashMap的優勢就是查找和操作的時間復雜度都是O(1);
-
數據結構簡單,對數據操作也簡單,Redis中的數據結構是專門進行設計的;
-
采用單線程,避免了不必要的上下文切換和競爭條件,也不存在多進程或者多線程導致的切換而消耗 CPU,不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有因為可能出現死鎖而導致的性能消耗;
-
使用多路I/O復用模型,非阻塞IO;
-
使用底層模型不同,它們之間底層實現方式以及與客戶端之間通信的應用協議不一樣,Redis直接自己構建了VM 機制 ,因為一般的系統調用系統函數的話,會浪費一定的時間去移動和請求;
2 單線程的,我們現在服務器都是多核的,那不是很浪費?
單機開多個Redis實例嘛。
單機會有瓶頸,那你們是怎么解決這個瓶頸的?
用到了集群的部署方式也就是Redis cluster,并且是主從同步讀寫分離,類似Mysql的主從同步,Redis cluster?支撐 N 個?Redis master node,每個master node都可以掛載多個?slave node。
這樣整個?Redis?就可以橫向擴容了。如果你要支撐更大數據量的緩存,那就橫向擴容更多的?master?節點,每個?master?節點就能存放更多的數據了。
3 Redis cluster
在生產環境中,我們主要還是采用分布式的部署方案,以盡量地避免單點問題,前面我們已經講過很多次了,單臺機器故障,在生產環境中是發生概率較高的事情,如果因為某臺機器故障而影響了整個系統,那只能說明這個系統非常的不健壯。
一組Redis Cluster是由多個Redis實例組成,官方推薦我們使用6實例,其中3個為主節點,3個為從結點。一旦有主節點發生故障的時候,Redis Cluster可以選舉出對應的從結點成為新的主節點,繼續對外服務,從而保證服務的高可用性。那么對于客戶端來說,知道對應的key是要路由到哪一個節點呢?原來,Redis Cluster 把所有的數據劃分為16384個不同的槽位,可以根據機器的性能把不同的槽位分配給不同的Redis實例,對于Redis實例來說,他們只會存儲部門的Redis數據,當然,槽的數據是可以遷移的,不同的實例之間,可以通過一定的協議,進行數據遷移。
數據獲取
客戶端是如何訪問Redis Cluster里面的數據呢?首先客戶端需要保存一份Redis Cluster槽相關的信息,也就是路由表,然后對即將訪問的key進行哈希計算,計算出對應的槽位,然后向對應的Redis實例發起查詢請求。如果訪問的Redis實例中,的確保存著對應槽的數據信息,就會進行返回,否則向客戶端返回一個Moved指令,讓客戶端到正確的地址進行獲取。
數據遷移
在分布式系統中,衡量一個系統好壞的一項重要指標,系統的擴展性。什么是系統的擴展性呢?就是今天你又10萬個用戶,需要4臺機器進行服務,如果明天的用戶數量增加到20萬了,是不是只要簡單的增加4臺機器就行,同時又不需要進行復雜的數據遷移。Redis Cluster便是如此,當你新增一些實例的時候,只需要將一部分槽位遷移到新的實例即可。在遷移的過程中,客戶端會先去舊的實例上去查詢數據,因為遷移正在發生,如果對應的數據還在本機上,那么直接返回,否則返回讓客戶端重定向到新的實例。客戶端先向新的機器發起ask指令,新實例返回成功后,再一次查詢最終的結果。
4?他們之間是怎么進行數據交互的?以及Redis是怎么進行持久化的?Redis數據都在內存中,一斷電或者重啟不就木有了嘛?
持久化的話是Redis高可用中比較重要的一個環節,因為Redis數據在內存的特性,持久化必須得有,我了解到的持久化是有兩種方式的。
- RDB:RDB 持久化機制,是對 Redis 中的數據執行周期性的持久化。
- AOF:AOF 機制對每條寫入命令作為日志,以 append-only 的模式寫入一個日志文件中,因為這個模式是只追加的方式,所以沒有任何磁盤尋址的開銷,所以很快,有點像Mysql中的binlog。
兩種方式都可以把Redis內存中的數據持久化到磁盤上,然后再將這些數據備份到別的地方去,RDB更適合做冷備,AOF更適合做熱備,比如我杭州的某電商公司有這兩個數據,我備份一份到我杭州的節點,再備份一個到上海的,就算發生無法避免的自然災害,也不會兩個地方都一起掛吧,這災備也就是異地容災,地球毀滅他沒辦法。
tip:兩種機制全部開啟的時候,Redis在重啟的時候會默認使用AOF去重新構建數據,因為AOF的數據是比RDB更完整的。。
那這兩種機制各自優缺點是啥?
優點:
他會生成多個數據文件,每個數據文件分別都代表了某一時刻Redis里面的數據,這種方式,有沒有覺得很適合做冷備,完整的數據運維設置定時任務,定時同步到遠端的服務器,比如阿里的云服務,這樣一旦線上掛了,你想恢復多少分鐘之前的數據,就去遠端拷貝一份之前的數據就好了。
RDB對Redis的性能影響非常小,是因為在同步數據的時候他只是fork了一個子進程去做持久化的,而且他在數據恢復的時候速度比AOF來的快。
缺點:
RDB都是快照文件,都是默認五分鐘甚至更久的時間才會生成一次,這意味著你這次同步到下次同步這中間五分鐘的數據都很可能全部丟失掉。AOF則最多丟一秒的數據,數據完整性上高下立判。
還有就是RDB在生成數據快照的時候,如果文件很大,客戶端可能會暫停幾毫秒甚至幾秒,你公司在做秒殺的時候他剛好在這個時候fork了一個子進程去生成一個大快照,哦豁,出大問題。
優點:
上面提到了,RDB五分鐘一次生成快照,但是AOF是一秒一次去通過一個后臺的線程fsync操作,那最多丟這一秒的數據。
AOF在對日志文件進行操作的時候是以append-only的方式去寫的,他只是追加的方式寫數據,自然就少了很多磁盤尋址的開銷了,寫入性能驚人,文件也不容易破損。
AOF的日志是通過一個叫非常可讀的方式記錄的,這樣的特性就適合做災難性數據誤刪除的緊急恢復了,比如公司的實習生通過flushall清空了所有的數據,只要這個時候后臺重寫還沒發生,你馬上拷貝一份AOF日志文件,把最后一條flushall命令刪了就完事了。
缺點:
一樣的數據,AOF文件比RDB還要大。
AOF開啟后,Redis支持寫的QPS會比RDB支持寫的要低,他不是每秒都要去異步刷新一次日志嘛fsync,當然即使這樣性能還是很高,我記得ElasticSearch也是這樣的,異步刷新緩存區的數據去持久化,為啥這么做呢,不直接來一條懟一條呢,那我會告訴你這樣性能可能低到沒辦法用的,大家可以思考下為啥喲。
?
你單獨用RDB你會丟失很多數據,你單獨用AOF,你數據恢復沒RDB來的快,真出什么時候第一時間用RDB恢復,然后AOF做數據補全,真香!冷備熱備一起上,才是互聯網時代一個高健壯性系統的王道。
?
假裝思考一會(不要太久,免得以為你真的不會),哦我想起來了,還有哨兵集群sentinel。
哨兵必須用三個實例去保證自己的健壯性的,哨兵+主從并不能保證數據不丟失,但是可以保證集群的高可用。
?
為啥必須要三個實例呢?我們先看看兩個哨兵會咋樣。
master宕機了 s1和s2兩個哨兵只要有一個認為你宕機了就切換了,并且會選舉出一個哨兵去執行故障,但是這個時候也需要大多數哨兵都是運行的。
那這樣有啥問題呢?M1宕機了,S1沒掛那其實是OK的,但是整個機器都掛了呢?哨兵就只剩下S2了,沒有哨兵去允許故障轉移了,雖然另外一個機器上還有R1,但是故障轉移就是不執行。
?
經典的哨兵集群是這樣的:
?
M1所在的機器掛了,哨兵還有兩個,兩個人一看他不是掛了嘛,那我們就選舉一個出來執行故障轉移不就好了。
?
-
集群監控:負責監控 Redis master 和 slave 進程是否正常工作。
-
消息通知:如果某個 Redis 實例有故障,那么哨兵負責發送消息作為報警通知給管理員。
-
故障轉移:如果 master node 掛掉了,會自動轉移到 slave node 上。
-
配置中心:如果故障轉移發生了,通知 client 客戶端新的 master 地址。
5 主從之間的數據怎么同步的么?
我先說下為啥要用主從這樣的架構模式,前面提到了單機QPS是有上限的,而且Redis的特性就是必須支撐讀高并發的,那你一臺機器又讀又寫,這誰頂得住啊,不當人啊!但是你讓這個master機器去寫,數據同步給別的slave機器,他們都拿去讀,分發掉大量的請求那是不是好很多,而且擴容的時候還可以輕松實現水平擴容。
你啟動一臺slave 的時候,他會發送一個psync命令給master ,如果是這個slave第一次連接到master,他會觸發一個全量復制。master就會啟動一個線程,生成RDB快照,還會把新的寫請求都緩存在內存中,RDB文件生成后,master會將這個RDB發送給slave的,slave拿到之后做的第一件事情就是寫進本地的磁盤,然后加載進內存,然后master會把內存里面緩存的那些新命名都發給slave。
?
6?數據傳輸的時候斷網了或者服務器掛了怎么辦啊?
傳輸過程中有什么網絡問題啥的,會自動重連的,并且連接之后會把缺少的數據補上的。
大家需要記得的就是,RDB快照的數據生成的時候,緩存區也必須同時開始接受新請求,不然你舊的數據過去了,你在同步期間的增量數據咋辦?是吧?
?
Redis的過期策略,是有定期刪除+惰性刪除兩種。
?
定期好理解,默認100ms就隨機抽一些設置了過期時間的key,去檢查是否過期,過期了就刪了。
7 為啥不掃描全部設置了過期時間的key呢?
假如Redis里面所有的key都有過期時間,都掃描一遍?那太恐怖了,而且我們線上基本上也都是會設置一定的過期時間的。全掃描跟你去查數據庫不帶where條件不走索引全表掃描一樣,100ms一次,Redis累都累死了。
1 如果一直沒隨機到很多key,里面不就存在大量的無效key了?
2 好問題,惰性刪除,見名知意,惰性嘛,我不主動刪,我懶,我等你來查詢了我看看你過期沒,過期就刪了還不給你返回,沒過期該怎么樣就怎么樣。
3 最后就是如果的如果,定期沒刪,我也沒查詢,那可咋整?
內存淘汰機制!
官網上給到的內存淘汰機制是以下幾個:
-
noeviction:返回錯誤當內存限制達到并且客戶端嘗試執行會讓更多內存被使用的命令(大部分的寫入指令,但DEL和幾個例外)
-
allkeys-lru: 嘗試回收最少使用的鍵(LRU),使得新添加的數據有空間存放。
-
volatile-lru: 嘗試回收最少使用的鍵(LRU),但僅限于在過期集合的鍵,使得新添加的數據有空間存放。
-
allkeys-random: 回收隨機的鍵使得新添加的數據有空間存放。
-
volatile-random: 回收隨機的鍵使得新添加的數據有空間存放,但僅限于在過期集合的鍵。
-
volatile-ttl: 回收在過期集合的鍵,并且優先回收存活時間(TTL)較短的鍵,使得新添加的數據有空間存放。
如果沒有鍵滿足回收的前提條件的話,策略volatile-lru, volatile-random以及volatile-ttl就和noeviction 差不多了。
參考文獻
'https://baijiahao.baidu.com/s?id=1643461909684941861&wfr=spider&for=pc
-
Redis中文官網
-
《Redis入門指南(第2版)》
-
《Redis實戰》
-
《Redis設計與實現》
-
《大型網站技術架構——李智慧》
-
《Redis 設計與實現——黃健宏》
-
《Redis 深度歷險——錢文品》
-
《億級流量網站架構核心技術——張開濤》
-
《中華石杉——石杉》
總結
以上是生活随笔為你收集整理的Redis哨兵、持久化、主从的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Postgresql下载地址及安装教程
- 下一篇: unity 延迟等待执行