緩存數據庫Redis


1、主流應用架構。

  1)、客戶端向后端發送請求的時候,會先去緩存層查詢,查詢看看是否有符合的數據。
  2)、如果有的話,直接返回。
  3)、如果在緩存層沒有查詢到,才回去存儲層去查詢。
  4)、去存儲層查詢叫做穿透查詢,就是穿透緩存去存儲層進行查詢。
  5)、從存儲層查詢出的數據回寫到緩存層,方便下次查詢的時候進行查詢,回寫的過程就是會種了。
  6)、此時,返回給客戶端,完成一次查詢操作。
  7)、緩存層還有一個熔斷機制,如果存儲層掛掉了,可以讓客戶端的請求直接打到緩存層上。
  8)、不管是否獲取到數據,直接進行返回,這樣可以在有損的情況了,提供服務。

2、緩存中間件,Memcache和Redis的區別。

  1)、Memcache,代碼層次類似Hash,非常簡單易用。支持簡單的數據類型,但是不支持數據的持久化存儲,如果服務器宕機了,數據是無法保存的。不支持主從同步,不支持分片機制。
  2)、Redis,數據類型豐富,支持數據磁盤持久化存儲,支持主從,支持分片。

 

3、為什么Redis能這么快?

答:Redis官方提供的100000+QPS,(QPS即query per second,每秒內查詢次數)。

  1)、完全基於內容,絕大部分請求是純粹的內存操作,執行效率高。Redis是采用單進程單線程模型的K-V數據庫,由c語言編寫,將數據存儲到內存中,讀寫數據的時候都不會受到硬盤IO速度的限制。
  2)、數據結構簡單,對數據操作也簡單。Redis不使用表,它的數據庫不會預定義或者強制要求用戶對redis存儲的不同數據進行關聯,因此性能相比關系型數據庫要高出不止一個量級,其存儲結構就是鍵值對,類似於hashMap,hashMap的優勢就是查詢,查詢的時間復雜度是O(1)的。
  3)、采用單線程,單線程也能處理高並發請求,想多核也可啟動多實例。在面對高並發的請求的時候,首先想要的是多線程來進行處理,將IO線程和業務線程分開,業務線程使用線程池來避免頻繁創建線程和銷毀線程,即便是一次請求,阻塞了也不會影響到其它請求。Redis單線程結構是指主線程是單線程的,主線程包含IO事件的處理,以及IO對應的相關請求的業務處理,此外,主線程還負責過期鍵的處理,復制協調,集群協調等等,這些除了IO事件之外的邏輯會被封裝成周期性的任務,由主線程周期性的處理,正因為采用單線程的設計,對於客戶端的所有讀寫請求,都由一個主線程串行的處理,因此多個客戶端同時對一個鍵進行寫操作的時候,就不會有並發的問題,避免了頻繁的上下文切換和鎖競爭,使得redis執行起來效率更高。單線程是可以處理高並發的請求的,並發並不是並行,並行性意外着服務器能夠同時執行幾個事情,具有多個計算的單元,而並發性IO流,意味着能夠讓一個計算單元來處理來自多個客戶端的流請求。Redis使用單線程配合上IO多路復用,將可以大幅度的提升性能,在多核CPU流行的今天,只要一個線程,只用一個核很浪費,CPU不是制約redis的性能瓶頸,此外,可以在多核的服務器中啟動多個實例來利用多核的特性。
注意,這里的單線程只是在處理我們的網絡請求的時候,只有一個單線程來處理,一個正式的Redis server,在運行的時候,肯定不止一個線程的,例如Redis在進行持久化的時候,會根據實際情況,以子進程子線程的方式執行。
  4)、使用多路I/O復用模型,非阻塞IO。Redis是跑在單線程中的,所有的操作都是按照順序線性執行的,但是由於讀寫操作等待用戶輸入或者輸出都是阻塞的,所以IO操作在一般情況下,往往不能直接返回,就會導致某一文件的IO阻塞,進而導致整個進程無法對其它客戶端提供服務。而IO多路復用就是為了解決這個問題而出現的。

4、多路I/O復用模型。

  答:FD,File Descriptor文件描述符。在操作系統中,一個打開的文件通過唯一的描述符進行引用,該描述符是打開文件的元素據到文件本身的映射,在linux中,該描述符稱為文件描述符即File Descriptor,文件描述符用一個整數來表示。

  1)、傳統的阻塞I/O模型,當使用read或者write的對某一個文件描述符FD進行讀寫的時候,如果當前的FD不可讀或者不可寫,整個Redis服務就不會對其它的操作做出相應,導致整個服務不可用,這也就是傳統意義上的阻塞IO模型,阻塞模型會影響其它FD對應的服務,所以在需要處理多個客戶端任務的時候,往往都不會使用阻塞模型。此時,需要一種更高效的IO模型來支持Redis的高並發處理,就是IO復用多路模型。

2)、多路I/O復用模型,最重要的函數調用就是Select系統調用。Select可以同時監控多個文件描述符的可讀,可寫情況,當其中的某些文件描述符可讀或者可寫的時候,select就會返回可讀以及可寫的文件描述符個數,也就是說,Selector是負責監聽我們的文件是否可讀或者可寫的,監聽的任務交給Selector之后呢,程序就可以做其它的事情了,而不被阻塞了。

3)、與此同時,也有其它的多路IO復用函數,Redis采用的IO多路復用函數:epoll、kqueue、evport、select。epoll、kqueue、evport相比select的性能更加優秀的,同時也可以支撐更多的服務。

  a)、Redis采用的多路復用函數是因地制宜的,Redis需要在多個平台下運行,為了最大化的提高執行效率和性能,會根據編譯平台的不同選擇不同的IO多路復用函數作為子模塊,提高給上層同一的接口。
  b)、Redis優先選擇時間復雜度為O(1)的IO多路復用函數作為底層實現。
  c)、以時間復雜度為O(n)的select作為保底。如果沒有epoll、kqueue、evport、就會使用select,會掃描全部的文件描述符,性能較差,時間復雜度是O(n)。
  d)、基於react設計模式監聽I/O事件。Redis采用react設計模式來實現文件處理器的,文件事件處理器使用IO多路復用m模塊,同時監聽多個FD,當accept,read,write,等事件產生的時候,事件處理器就會回調FD綁定的事件處理器,雖然整個事件處理器是在單線程運行的,但是通過IO多路復用模塊的引用,實現了同時對多個FD讀寫的監控,提高了網絡通信模型的性能,同時來保證了整個Redis服務實現的簡單。

 

5、Redis的數據類型(Redis底層數據類型基礎,簡單動態字符串、鏈表、字典、跳躍表、整數集合、壓縮列表、對象)。

  1)、String,最基本的數據類型,二進制安全的。常用的k-v鍵值對,最大可以存儲512兆,String類型二進制安全的,意思是Redis的String包含任何數據,比如圖片或者序列化的對應。Redis的單個操作都是原子性的,原子性的意思就是一個事務是一個不可分割的最小工作單位,事務中包括的諸多操作,要么都做,要么都不做。Redis的原子性使得我們不用考慮並發性,可以方便的利用原子性操作Incr來實現簡單的計數功能。
  2)、Hash,String元素組成的字典,適合用於存儲對象,Hash是一個映射表。
  3)、List,列表,按照String元素插入順序排序,是簡單的字符串列表。類似棧,先進后出的順序。可以實現最新消息排行榜的功能,越新插入的消息越能在榜首顯示。
  4)、Set,String元素組成的無序集合,通過哈希表實現,不允許重復。所以添加、刪除、查找的復雜度是O(1)的。提供了並集、交集、叉集功能。
  5)、Sorted Set,通過分數來為集合中的成員進行從小到大的排序。Redis的zset和set集合一樣,也是String集合組成的集合,且不允許重復的成員,不同的是有序集合每個元素都會關聯一個double類型的分數,redis正式通過這個分數呢,來為集合中的成員進行從小到大的排序。zset的成員是唯一的,但是分數呢卻可以重復的。分數越小越靠前。
  6)、用於計數的HyperLoglog,用於支持存儲地理位置信息的Geo等等。

 

6、在Redis中,從海量Key里面查詢出某一固定前綴的Key?

答:比如問題這樣的,假如Redis里面有一億個key,其中十萬個key是以某個固定已知的前綴開頭的,如何將它們全部找出來。留意細節,摸清楚數據規模,即問清楚邊界。如果問題是從Redis里面查詢出某一固定前綴的Key,記得問清楚數據量。

  1)、此時,如果直接回答,使用keys pattern,這樣查找所有符合給定模式pattern的key。注意,使用keys后接pattern便能按照某個指定的模式搜出某種模式的key來。由於keys一次性返回所有的key,如果key的數量過大,會導致客戶端被卡住的,如果Redis中的key非常多的時候,對內存的消耗和Redis服務器都是一個隱患。Keys指令一次性返回所有匹配的key,鍵的數量過大會使服務卡頓。
  2)、Scan指令,可以無阻塞的提取出指定的默認的key列表,scan每次執行只會返回少量元素,所以可以用於生產環境的,而不會出現像keys命令帶來的可能會阻塞服務器的問題。

  3)、Scan指令,模式如下所示:

Scan cursor [MATCH pattern] [COUNT count],其中cursor是游標,MATCH pattern是需要查找的模式。

    a)、Scan指令是一個基於游標的迭代器,需要基於上一次的游標延續之前的迭代過程。意味着命令每次被調用都需要使用上一次調用返回的游標作為該次調用的游標參數,依次來延續之前的迭代過程。
    b)、以0作為游標開始一次新的迭代,直到命令返回游標0完成一次遍歷。當scan指令的游標參數即cursor被置為0的時候,服務器將開始一次新的迭代,而當服務器向用戶返回值為0的游標的時候,就表示迭代完成,以0作為游標開始新一次的迭代,一直調用scan指令直到命令返回游標0,稱這個過程為一次完整的遍歷。
    c)、不保證每次執行都返回某個給定數量的元素,支持模糊查詢。Scan增量式迭代命令並不保證每次執行都會返回某個給定數量的元素,甚至可能返回0個元素,但只要命令返回的游標不是0,應用程序就不應該將迭代視作結束,命令返回的元素數量總是符合一定的規則的。對於一個大數據集來說,增量式迭代命令每次最多可能會返回數十個元素,而對於一個足夠小的數據集來說,可能會一次迭代返回所有的key,類似於keys指令,scan可以通過給定match參數的方式傳入要查找鍵位的模糊匹配方式,讓命令只返回和給定模式下向匹配的元素。
    d)、一次返回的數量不可控,只能是大概率符合count參數。此外,對於增量式迭代命令是沒有辦法保證每次迭代所返回的元素數量的,我們可以使用count選項對命令的行為進行一定程度的調整,count選項的作用就是讓用戶告知迭代命令,在每次迭代中,應該從數據集里返回多少元素,使用count選項對於增量式迭代命令相當於是一種提示,大多數情況下,這種提示都是比較有效的控制返回的數量的。值得注意的是,count數量並不能嚴格的控制返回的key的數量,只能說是一個大致的約束,並非每次迭代都會返回count數量的約束,用戶可以根據自己的需求在每次迭代中隨意改變count的值,只要記得將上次迭代返回的游標用到下次迭代的游標里面就可以了。    
    注意:可能會獲取到重復key的問題,所以在程序中進行處理的。

 

7、分布式鎖需要解決的問題?

答:分布式鎖是控制分布式系統或者不同系統之間共同訪問共享資源的一種鎖的實現,如果不同的系統或者同一個系統不同主機之間共享了某個資源的時候,往往需要互斥來防止彼此干擾,進而保證一致性。

  1)、互斥性。任意時刻只能有一個客戶端獲取鎖,不能同時有兩個客戶端獲取到鎖。
  2)、安全性。鎖只能被持有該鎖的客戶端刪除,不能由其它客戶端刪除掉。
  3)、死鎖。獲取鎖的客戶端因為某些原因而宕機,而未能釋放鎖,其它客戶端再也無法獲取到該鎖,而導致的死鎖,此時需要有機制避免這種問題的發生 。
  4)、容錯。當部分節點宕機的時候呢,客戶端仍然能夠獲取鎖和釋放鎖。


8、如何通過Redis實現分布式鎖?

答:SETNX key value,如果key不存在,則創建並賦值。SETNX是set if not exist即如果key不存在,則創建並賦值。時間復雜度是O(1),返回是設置成功返回1,設置失敗返回0。
  正因為SETNX的操作是原子性的,因此初期便被用在實現分布式鎖,在執行某段代碼邏輯的時候,先嘗試使用SETNX對某個key設值,如果設值成功,則證明此時沒有別的線程在執行該段代碼,或者說占用該獨占資源,這個時候線程就可以順利的去執行該段代碼邏輯了,如果設值失敗,則證明此時有別的程序或者線程占用該資源,那么當前線程就需要等待直至設值SETNX成功,如果設值SETNX的key,這個key就會長久有效了,后續線程如何能再次獲得到鎖,此時需要給該key設值一個過期時間。


9、如何解決SETNX長期有效的問題?

答:EXPIRE key seconds。
  1)、設值key的生存時間,當key過期的時候(生存時間為0),會被自動刪除。
  2)、使用EXPIRE設值過期時間的缺點就是原子性得不到滿足。如果SETNX與EXPIRE結合使用,它們分別都是原子性的,但是組合到一起卻不是原子性的。


10、如何通過Redis實現分布式鎖?

答:Redis2.6.12之后,通過set操作,將SETNX和EXPIRE柔和到一起去執行,此時就滿足了分布式鎖的原子性需求。命令格式,SET key value [EX seconds] [PX milliseconds] [NX][XX]。
  1)、EX seconds,設值鍵的過期時間為second秒。
  2)、PX milliseconds,設值鍵的過期時間為millisecond毫秒。
  3)、NX,只在鍵不存在的時候,才對鍵進行設值操作。效果等同於SETNX。
  4)、XX,只在鍵已經存在的時候,才對鍵進行設置操作。
  5)、SET操作成功完成時候,返回OK,否則返回nil。



11、大量的key同時過期的注意事項,如何避免系統卡斷現象?

答:由於大量的key過期時間過於集中,集中過期,到過期的那個時間點,由於清除大量的key很耗時,會出現短暫的卡頓現象。

  1)、解決方案,在設值key的過期時間的時候,給每個key加上隨機值就行了,使得過期時間分散一些,很大程度上避免卡頓現象的發生。   

 

12、如何實現異步隊列,如何使用Redis做異步隊列?

答:使用List作為隊列,rpush生產消息,lpop消費消息。rpush與lpop組合是先進先出的效果,lpush與lpop組合是先進后出的效果。
  1)、在這種生產者和消費者的模式里面,當lpop沒有消息的時候,說明消息暫時被消費完畢,並且生產者還沒有來得及生產消息。
  2)、缺點,就是沒有等待隊列里有值就直接消費。lpop是不會等待隊列里有值才會去消費的。
  3)、彌補,可以通過在應用層引入sleep機制去調用lpop重試。進而實現一個簡單的異步隊列。
  4)、如果不想使用sleep重試,可以使用BLPOP的方式。BLPOP key [key...] timeout,阻塞直到隊列有消息或者超時。在沒有消息的時候會阻塞住,直到消息的到來或者超時。BLPOP可以替代sleep做更精准的阻塞控制。
這種方式的缺點,就是只能供一個消費者消費,讓lpop或者blpop。
  5)、是否可以只生產一次,就讓多個消費者消費呢,可以使用redis的pub/sub,主題訂閱者模式。


13、Redis的主題訂閱者模式。

答:pub/sub,主題訂閱者模式,可以實現一對多的消費隊列。通過訂閱的方式可以使得消費者可以只獲取到需要它們關心的並且消費的數據。
  1)、發送者(pub)發送消息,訂閱者(sub)接收消息。
  2)、 訂閱者可以訂閱任意數量的頻道。頻道即topic,是消費者關注的主題。
  3)、pub/sub的缺點,就是消息的發布是無狀態的,即發布完消息之后,無法保證消息是否被接收到,是否在傳輸過程中丟失,對於發布者來說,消息是即發即失的,無法保證可達。此時,如果某個消費者在生產者發送消息的時候下線了,重新上線之后是接收不到該消息的。解決這個問題,就要使用專業的消息隊列了如kafka等。

 

14、Redis如何做持久化?

答:Redis提供了三種持久化的方案,將內存中的數據保存到磁盤中。

  1)、RDB(快照)持久化,快照方式持久化,保存某個時間點的全量數據快照。是一個二進制文件的。

  2)、RDB持久化的缺點,缺點一,內存數據的全量同步,數據量大會由於I/O而嚴重影響性能的。每次快照持久化都是將快照數據完整的寫入到磁盤一次,並不是增量的只同步臟數據,如果數據量大的話,並且寫操作比較多的時候b必然會引起大量的磁盤IO操作,可能會嚴重性能。缺點二,可能會因為Redis掛掉而丟失從當前至最近一次快照期間的數據,由於快照方式是在一定間隔時間做一次的快照后的所有修改,如果應用要求bbu不能丟失任何修改的話,可以采用AOF。

 1 ################################ SNAPSHOTTING  ################################
 2 #
 3 # Save the DB on disk:
 4 #
 5 #   save <seconds> <changes>
 6 #
 7 #   Will save the DB if both the given number of seconds and the given
 8 #   number of write operations against the DB occurred.
 9 #
10 #   In the example below the behaviour will be to save:
11 #   after 900 sec (15 min) if at least 1 key changed
12 #   after 300 sec (5 min) if at least 10 keys changed
13 #   after 60 sec if at least 10000 keys changed
14 #
15 #   Note: you can disable saving completely by commenting out all "save" lines.
16 #
17 #   It is also possible to remove all the previously configured save
18 #   points by adding a save directive with a single empty string argument
19 #   like in the following example:
20 #
21 #   save ""
22 
23 # 持久化的時間策略。配置這么多條規則的意思是redis每個時段的讀寫請求肯定是不均衡的,為了平衡性能與數據安全,可以自由的什么情況下觸發備份。可以根據自身redis的寫入情況合理配置
24 save 900 1            # 表示900秒之內如果有一條是寫入指令就觸發產生一次快照。產生一次快照就可以理解為是一次備份了。
25 save 300 10         # 表示300秒以內如果有10條寫入就會產生快照。如果變動數是大於0但是還沒有到10條的話,就會等到900秒過后才去做備份。
26 save 60 10000        # 表示60秒內如果有一萬條寫入就進行一次備份。
27 save ""                # 禁用RDB配置。    
28 
29 # By default Redis will stop accepting writes if RDB snapshots are enabled
30 # (at least one save point) and the latest background save failed.
31 # This will make the user aware (in a hard way) that data is not persisting
32 # on disk properly, otherwise chances are that no one will notice and some
33 # disaster will happen.
34 #
35 # If the background saving process will start working again Redis will
36 # automatically allow writes again.
37 #
38 # However if you have setup your proper monitoring of the Redis server
39 # and persistence, you may want to disable this feature so that Redis will
40 # continue to work as usual even if there are problems with disk,
41 # permissions, and so forth.
42 
43 # 設值成yes表示當備份進程出錯的時候,主進程就停止接收新的寫入操作了,這樣做是為了保護持久化的數據一致性的問題。如果自己的業務有完善的監控系統,可以禁止此項配置,否則開啟。
44 stop-writes-on-bgsave-error yes
45 
46 # Compress string objects using LZF when dump .rdb databases?
47 # For default that's set to 'yes' as it's almost always a win.
48 # If you want to save some CPU in the saving child set it to 'no' but
49 # the dataset will likely be bigger if you have compressible values or keys.
50 
51 # 和rdb的壓縮相關的,設置成yes就表示的是在備份的時候需要將rdb文件進行壓縮后才去做保存。建議設置為no,因為redis本身是cpu密集型服務器,再開啟壓縮,會帶來更多的cpu的消耗,相比硬盤成本,cpu更值錢。
52 rdbcompression yes

 

15、RDB的創建與載入,RDB文件可以通過兩個命令來生成。

  1)、SAVE,阻塞Redis的服務器進程,直到RDB文件被創建完畢。SAVE很少被使用,因為save操作是在主線程中保存快照的,由於Redis是用一個主線程來處理所有的請求的,這種方式會阻塞所有的客戶端請求。
  2)、BGSAVE,fork出一個子進程來創建RDB文件,記錄接收BGSAVE當時的數據庫狀態,父進程繼續處理接收到的命令,子進程完成文件的創建之后會發送信號給父進程即Redis的主進程,而於此同時,父進程處理命令的同時,通過輪詢來接收子進程的信號,不阻塞服務器進程。BGSAVE指令是使用后台方式保存RDB文件的,調用此命令后會立刻返回OK返回碼,Redis會產生一個子進程進行處理,並立刻恢復對客戶端的服務,在客戶端可以使用last save這個指令,產看操作是否成功,last save記錄了上一次成功執行save或者bgsave命令的時間。
  3)、可以使用java計時器或者quartz來定期調用redis的bgsave指令去備份rdb文件,並按照時間戳存儲不同的rdb文件,作為redis某段時間的全量備份腳本。

16、自動化觸發RDB持久化的方式。自動觸發的場景主要有以下幾點。

  1)、根據redis.conf配置里面的save m n規則定時觸發,使用的bgsave,這里面的save使用的是bgsave異步備份。
  2)、主從復制的時候,主節點自動觸發。從節點全量復制的時候,主節點發送RDB文件給從節點完成復制操作。主節點就會觸發bgsave。
  3)、執行Debug Reload。
  4)、執行shutdown且沒有開啟AOF持久化。

 

17、Redis的GBSAVE的原理

  1)、在執行了GBSAVE指令之后,首先回去檢查當前子進程有沒有正在執行的AOF/RDB子進程,有的話返回錯誤。這樣做是為了防止子進程之間的競爭,也就意味着在執行GBSAVE期間呢,客戶端發送的SAVE/GBSAVE命令會被服務器j拒絕執行,如果此時沒有發生相關子進程,則會觸發持久化。
  2)、觸發了持久化,就會調用redis源碼里面的rdbSaveBackground方法執行fork系統調用。其實執行BGSAVE指令來生成RDB文件的時候,本質就是調用了操作系統的系統調用fork指令。
  3)、系統調用fork(),就是用來創建進程的,而Linux下fork系統調用實現了Copy-on-Write寫時復制。傳統方式下fork函數在創建子進程的時候直接把所有的資源復制給子進程,這種實現方式簡單,但是效率低下,而且復制的資源k可能對子進程毫無用處,linux為了降低創建子進程的成本,改進fork實現方式,當父進程創建子進程的時候,內核只為子進程創建虛擬空間,父子兩個進程使用的是相同的物理空間,只有父子進程發生更改的時候才會為子進程分配獨立的物理空間。
  4)、改進的實現方式稱為寫時復制,Copy-on-Write(簡稱COW)是計算機程序設計l領域的優化策略,核心思想如果有多個調用者同時要求相同資源(如內存或者磁盤上的數據存儲),它們會共同獲取相同的指針指向相同的資源,直到某個調用者 試圖修改資源的內容的時候,系統才會真正復制一份專用副本給該調用者,而其它調用者所見到的最初的資源仍然保持不變。

 

18、Redis如何做持久化?

答:AOF(append-only-file)持久化,通過保存Redis服務器所執行的寫狀態來記錄數據庫的。

  1)、記錄下除了查詢以外的所有變更數據庫狀態的指令。AOF(append-only-file)持久化是備份數據庫接收到的指令所有被寫入AOF的命令都是以redis協議格式來保存的。
  2)、在AOF中,以append的形式追加保存到aof文件中,以增量的形式。數據庫會記錄下所有變更數據庫狀態的指令,除了指定數據庫的查詢命令,其它的命令都是來自client的。
  3)、注意,aof持久化默認是關閉的,可以通過修改refis.conf的配置appendonly no修改為appendonly yes即可,生成的文件名稱是appendonly.aof。修改配置需要重啟redis服務器。
  4)、appendfsync everysec該配置主要用來配置aof文件的寫入方式的,可以接收三個不同的參數分別是,always、everysec、no,always表示一旦緩存區的內容發生變化,就總是及時的將緩存區的內容寫入到aof中,everysec是將緩存區的內容每隔一秒去寫入到aof中,no是將寫入aof的操作交由操作系統來決定,一般而言,為了提高效率,操作系統會將緩存區被填滿才會開始同步數據到磁盤中。一般推薦everysec默認的方式,速度比較快,安全性比較高。

  5)、AOF日志文件是一個純追加的文件,就算遇到突然斷電也可以盡最大權力去保證數據的無損。

 

19、AOF持久化,日志重寫解決AOF文件大小不斷增大的問題,Redis支持在不中斷服務的情況下,在后台重建AOF文件,原理如下:

  1)、首先調用fork(),創建一個子進程。
  2)、子進程把新的AOF寫到一個臨時文件里面,新的AOF的重寫是直接把當前內存的數據生成對應的命令,並不需要讀取老的AOF文件進行分析或者合並,不依賴原來的AOF文件。
  3)、主進程持續將新的變動同時寫到內存和原來的AOF里面。這樣即使寫入失敗,也能保證數據的安全。
  4)、主進程獲取子進程重寫AOF的完成信號,往新AOF同步增量變動。
  5)、使用新的AOF文件替換掉舊的AOF文件。

 

20、Redis數據的恢復,RDB和AOF文件共存情況下的恢復流程,就是一台服務器既有RDB文件,又有AOF文件。

  1)、其實想要從這些文件中恢復數據,只要重啟Redis即可。

 

21、RDB和AOF的優缺點?

  1)、RDB優點,RDB本質上是一個內存快照,保存了創建RDB文件那個時間點的Redis全量數據,全量數據快照,文件小,創建恢復快。
  2)、RDB缺點,無法保存最近一次快照之后的數據。
  3)、AOF優點,AOF本質上是一份執行日志,保存所有被Redis更改的指令,可讀性高,適合保存增量數據,數據不易丟失。
  4)、AOF缺點,文件體積大,恢復時間長。

 

22、Redis4.0之后,推出了結合AOF和RDB的混合模式,並且作為默認的方式來使用。即使用RDB作為全量備份,AOF作為增量備份,來提升備份的效率。

  1)、BGSAVE做鏡像全量持久化,AOF做增量持久化,因為BGSAVE會耗費較長時間,不夠實時,在停機的時候會導致大量丟失數據的問題,需要AOF配合使用,在Redis重啟的時候會使用BGSAVE持久化文件,重新構建內容,再使用AOF重放近期的操作指令,來實現完整恢復之前的狀態。AOF和RDB的混合模式目前推薦的持久化方式。
  2)、AOF重寫機制,它其實y也是先寫一份全量數據到AOF文件中,再追加增量,只不過全量數據是以redis命令格式寫入的,那么是否可以先以RDB格式寫入全量數據,再追加增量數據呢,這樣既可以提高重新和恢復速度,也可以減少文件的大小,還同時可以保證數據的完整性,能夠結合RDB和AOF的優點,AOF和RDB的混合模式正是在這種需求下誕生的。在此種方式下,子進程在做AOF重寫的時候,會通過管道從父進程讀取增量數據並緩存下來,那么在以RDB格式保存全量數據的時候,也會從管道讀取數據,同時不會造成管道的阻塞,也就是說,AOF文件前半段是RDB格式的全量數據,而后半段是Redis命令格式的增量數據。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM